Vue implements chat interface

Vue implements chat interface

This article example shares the specific code of Vue to realize the display of the chat interface for your reference. The specific content is as follows

1. Functional requirements

Choose to chat with different people based on the index

2. Code display

mock.js:

import Mock from 'mockjs'
Mock.mock("/chatchild",{
    'result':[
        {
            id:"001",
            imgurl:"/static/image/10.jpg",
            name:"XKDK",
            date:"09:23",
            words:"Haha, ok"
        },
        // ... ...
    ]
});
export default Mock

userinfo.js:

let usermsg = {
    id:"122",
    imgurl:"/static/image/8.jpg",
    words:"Yes!",
    data:{
        id:"1529",
        imgurl:"/static/image/7.jpg",
        name:"Yi An Jushi",
        words:[
            {info:"Are you there?"},
            {info:"Not in"},
            {info:"Have you submitted the draft?"},
            {info:"I have been watching TV series since lunch today"},
            {info:"I found out that I am really a homebody"},
            {info:"Hahaha"},
            {info:"Let's have dinner together when I have time"},
            {info:"hmm"},
            {info:"It won't have much of an impact anyway"}
        ]
    }
}
export default usermsg

index.js:

import Vue from 'vue'
import Router from 'vue-router'
import Chat from '../components/Chat.vue'
import ChatDetail from '../components/Pages/ChatDetail.vue'

Vue.use(Router)

export default new Router({
  routes: [
    {
      path: '/Chat ',
      component: Chat 
    },
    {
      path:'/ChatDetail',
      component:ChatDetail
    }
  ]
})

// Code to solve routing errors const originalPush = Router.prototype.push
Router.prototype.push = function push(location) {
    return originalPush.call(this, location).catch(err => err)
}

Chat.vue:

<template>
  <div id="chat">
    <Bottom />
    <Header :name="msg" />
    <div class="chat_alluser">
      <div ref="chatuser" @click="checkChild(index)" class="chatuser" v-for="(item,index) in chat" :key="index">
        <ChatChild :imgsrc="item.imgurl" :nickname="item.name" :time="item.date" :word="item.words" />
      </div>
    </div>
  </div>
</template>

<script>
import Bottom from "../components/Menu/Bottom";
import Header from "../components/Menu/Header";
import ChatChild from "../components/Pages/ChatChild";
export default {
  name: "Chat",
  components:
    Bottom: Bottom,
    Header: Header,
    ChatChild: ChatChild
  },
  data() {
    return {
      msg: "WeChat",
      chat: null,
      name: null
    };
  },
  mounted() {
    this.$axios.get("/chatchild").then(res => {
      this.chat = res.data.result;
    });
  },
  methods: {
    checkChild(index) {
      this.$refs.chatuser[index].style.backgroundColor = "rgb(240,240,240)";
      // After the dynamic DOM element rendering is completed, jump to another interface (ChatDetail)
      // Get the dynamic name
      let username = this.chat[index].name;
      this.$nextTick(() => {
        this.$router.push({
          path: "/ChatDetail",
          query: { name: username }
        });
      });
    }
  }
};
</script>

<style lang="scss" scope>
#chat {
  width: 100%;
  .chat_alluser {
    margin-bottom: 7.5rem;
    .chatuser {
      position: relative;
      top: 3.5rem;
      padding: 0.3rem 0;
    }
  }
}
</style>

The parent component uses the properties and methods in the child component:
Define a ref attribute on a child component in a parent component, using the this.$refs.name. attribute or this.$refs.name. method

ChatChild.vue:

<template>
  <div id="chatchild">
    <div class="photo">
      <img :src="imgsrc" alt />
    </div>
    <div class="content">
      <div>
          <span class="content_nickname">{{nickname}}</span>
          <span class="content_time">{{time}}</span>
      </div>
      <span class="content_word">{{word}}</span>
    </div>
  </div>
</template>

<script>
export default {
  name: "ChatChild",
  props:{
    'imgsrc':String,
    'nickname':String,
    'time':String,
    'word':String
  }
};
</script>

<style lang="scss" scope>
#chatchild {
  width: 100%;
  height: 5rem;
  display: flex;
  flex-direction: row;
  box-sizing: border-box;
  .photo {
    flex: 1;
    height: 5rem;
    img{
        object-fit: cover;
        width: 4rem;
        height: 4rem;
        border-radius: 5px;
        display: block;
        margin: 0 auto;
        margin-top: 0.5rem;
        margin-left: 1rem;
    }
  }
  .content {
    flex: 4;
    height: 5rem;
    border-bottom: 0.5px solid rgb(240, 240, 240);
    padding-left: 0.5rem;
    padding-top: 0.5rem;
    box-sizing: border-box;
    div{
      .content_nickname{
        display: inline-block;
        font-size: 1.1rem;
        margin-top: 0.3rem;
      }
      .content_time{
        float: right;
        margin-right: 1rem;
        color: rgb(209, 206, 206);
        font-size: 0.8rem;
      }
    }
    .content_word{
      color: rgb(209, 206, 206);
      font-size: 0.8rem;
      display: block;
      margin-top: 0.5rem;
    }
  }
}
</style>

ChatDetail.vue:

<template>
  <div id="chatdetail">
    <div class="chattop">
      <div @click="goback" class="chattop_back">
        <icon-svg icon-class="houtui_shangyibu_zuojiantou_shangyiye" />
      </div>
      <div class="chattop_name">{{name}}</div>
      <div class="chattop_more">
        <icon-svg icon-class="gengduo" />
      </div>
    </div>
    <div class="chatcontent">
      <ChatMsg ref="chatmsg" />
    </div>
    <div class="chatfooter">
      <div @click="changeSound">
        <icon-svg :icon-class="issound" />
      </div>
      <div>
        <input ref="sendcontent" @keypress="sendmsg" :type="istype" :value="isvalue" />
      </div>
      <div>
        <icon-svg icon-class="biaoqing" />
      </div>
      <div>
        <icon-svg icon-class="del" />
      </div>
    </div>
  </div>
</template>

<script>
import ChatMsg from "./ChatMsg";
export default {
  name: "ChatDetail",
  data() {
    return {
      name: null,
      issound: "xiaoxitongzhi",
      istype: "text",
      isvalue: "",
      isshow: false,
      tomsg: "",
      msgchild: null
    };
  },
  components:
    ChatMsg: ChatMsg
  },
  mounted() {
    this.name = this.$route.query.name;
    this.msgchild = this.$refs.chatmsg;
  },
  methods: {
    // Perform the return operation goback() {
      this.$router.go(-1);
    },
    // Switch input type changeSound() {
      // Define a variable isshow:false in data, and use this.isshow and !this.isshow to switch if (!this.isshow) {
        this.isshow = true;
        this.issound = "yuyin";
        this.istype = "button";
        this.isvalue = "Press and hold to speak";
      } else {
        this.isshow = false;
        this.issound = "xiaoxitongzhi";
        this.istype = "text";
        this.isvalue = "";
      }
    },
    // Send a message sendmsg(e) {
      // 1. Use ref to define the input text box for entering the reply content, and define the sendcontent variable to receive its value (the input content)
      let sendcontent = this.$refs.sendcontent.value;
      if (e.keyCode === 13 && sendcontent.split(" ").join("").length !== 0) {
        // 2. Use tomsg to receive the sendcontent (the value entered in the text box) in the ChatDetail (parent) component this.tomsg = sendcontent;
        // 3. Define the ChatMsg (child) component with ref, and use $refs to obtain it in mounted, that is, this.msgchild
        // 4. Call the method in the child component and pass tomsg to the ChatMsg (child) component (specific chat content) this.msgchild.saveMsg(this.tomsg);
        // 5. After sending a message, you need to clear the text box this.$refs.sendcontent.value = "";
        // When pressing Enter, call the random message method of the child component this.msgchild.randomMsg();
      }
    }
  }
};
</script>

<style lang="scss" scope>
#chatdetail {
  position: relative;
  background-color: rgb(238, 212, 238);
  .chattop {
    position: fixed;
    top: 0;
    left: 0;
    z-index: 10;
    width: 100%;
    height: 3.5rem;
    line-height: 3.5rem;
    background-color: rgb(240, 240, 240) !important;
    display: flex;
    flex-direction: row;
    .chattop_back {
      flex: 1;
      margin-left: 1rem;
    }
    .chattop_name {
      flex: 20;
      text-align: center;
    }
    .chattop_more {
      flex: 1;
      margin-right: 1rem;
    }
  }
  .chatcontent {
    width: 100%;
    height: 100%;
  }
  .chatfooter {
    position: fixed;
    left: 0;
    bottom: 0;
    z-index: 10;
    width: 100%;
    height: 3.5rem;
    line-height: 3.5rem;
    text-align: center;
    background-color: rgb(240, 240, 240) !important;
    display: flex;
    flex-direction: row;
    div:nth-child(1),
    div:nth-child(3),
    div:nth-child(4) {
      flex: 1;
      svg {
        font-size: 1.5rem;
        margin-top: 0.9rem;
      }
    }
    div:nth-child(2) {
      flex: 5;
      input {
        width: 100%;
        height: 2.5rem;
        outline: none;
        padding-left: 0.5rem;
        box-sizing: border-box;
        height: 2.5rem;
        margin-top: 0.5rem;
        border-style: none;
        font-size: 0.9rem;
        border-radius: 4px;
        background-color: #fff;
        color: #000;
      }
    }
  }
}
</style>

ChatMsg.vue:

<template>
  <div id="chatmsg" ref="msg">
    <!-- Dynamic creation -->
    <div v-for="(item,index) in lists" :key="index">
      <div v-if="item.id==122" class="user">
        <div v-scroll>
          <img :src="item.face" alt />
          <div class="bubble">
            <span>{{item.word}}</span>
          </div>
        </div>
      </div>
      <div v-if="item.id==1529" class="touser">
        <div v-scroll>
          <img :src="item.face" alt />
          <div class="tobubble">
            <span>{{item.word}}</span>
          </div>
        </div>
      </div>
    </div>
  </div>
</template>

<script>
import userinfo from "./userinfo";
export default {
  name: "ChatMsg",
  data() {
    return {
      userimg: "",
      lists: []
    };
  },
  mounted() {
    this.userid = userinfo.id;
    this.userimg = userinfo.imgurl;
  },
  // vue automatically scrolls to the bottom directives: {
    scroll: {
      inserted(el) {
        el.scrollIntoView();
      }
    }
  },
  methods: {
    saveMsg(tomsg) {
      this.lists.push({
        id: this.userid,
        face: this.userimg,
        word: tomsg
      });
    },
    randomMsg() {
      let touserdata = userinfo.data;
      this.lists.push({
        id: touserdata.id,
        face: touserdata.imgurl,
        word:
          touserdata.words[Math.floor(Math.random() * touserdata.words.length)]
            .info
      });
    }
  }
};
</script>

<style lang="scss" scope>
#chatmsg {
  position: relative;
  top: 3.5rem;
  width: 100%;
  min-height: 44rem;
  background-color: rgb(238, 212, 238);
  margin-bottom: 3.5rem;
  overflow-x:hidden;
  overflow-y: auto;
  .user {
    position: relative;
    width: 100%;
    overflow: hidden;
    margin: 0.8rem 0;
    img {
      object-fit: cover;
      width: 3rem;
      height: 3rem;
      border-radius: 3px;
      float: right;
      margin-right: 1rem;
    }
    .bubble {
      position: relative;
      float: right;
      margin-right: 1rem;
      padding: 0.8rem;
      box-sizing: border-box;
      border-radius: 3px;
      max-width: 65%;
      background-color: rgb(116, 228, 116);
      span {
        height: 1.25rem;
        line-height: 1.25rem;
      }
    }
    .bubble::after {
      position: absolute;
      right: -1.3rem;
      top: 0.8rem;
      content: "";
      width: 0;
      height: 0;
      border: 0.7rem solid;
      border-color: transparent transparent transparent rgb(116, 228, 116);
    }
  }
  .touser {
    position: relative;
    width: 100%;
    overflow: hidden;
    margin: 0.8rem 0;
    img {
      object-fit: cover;
      width: 3rem;
      height: 3rem;
      border-radius: 3px;
      float: left;
      margin-left: 1rem;
    }
    .tobubble {
      position: relative;
      float: left;
      margin-left: 1rem;
      padding: 0 0.7rem;
      box-sizing: border-box;
      border-radius: 3px;
      max-width: 65%;
      background-color: rgb(116, 228, 116);
      line-height: 3rem;
    }
    .tobubble::after {
      position: absolute;
      left: -1.3rem;
      top: 0.8rem;
      content: "";
      width: 0;
      height: 0;
      border: 0.7rem solid;
      border-color: transparent rgb(116, 228, 116) transparent transparent;
    }
  }
}
</style>

3. Directory Structure

The above is the full content of this article. I hope it will be helpful for everyone’s study. I also hope that everyone will support 123WORDPRESS.COM.

You may also be interested in:
  • Vue+express+Socket realizes chat function
  • Vue realizes web online chat function
  • Vue+web terminal imitates WeChat web version chat room function
  • Vue.js imitates WeChat chat window to display component functions
  • Vue + socket.io implements a simple chat room sample code
  • A single-page application function imitating mobile QQ based on Vue2 (access to chatbot)
  • How to use RongCloud IM to implement chat function in Vue Cli 3 project
  • WeChat robot chat function example implemented by Vue [with source code download]
  • Multi-person online chat room based on vue and websocket
  • Vue+ssh framework to realize online chat

<<:  Oracle VM VirtualBox installation of CentOS7 operating system tutorial diagram

>>:  MySQL character set garbled characters and solutions

Recommend

Detailed explanation of mysql user variables and set statement examples

Table of contents 1 Introduction to user variable...

Let's talk about what JavaScript's URL object is

Table of contents Overview Hash Properties Host p...

Detailed usage of docker-maven-plugin

Table of contents Docker-Maven-Plugin Maven plugi...

Tutorial on Migrating Projects from MYSQL to MARIADB

Prepare the database (MySQL). If you already have...

Vue uses filters to format dates

This article example shares the specific code of ...

Record the process of connecting to the local Linux virtual machine via SSH

Experimental environment: Physical machine Window...

Steps to package and release the Vue project

Table of contents 1. Transition from development ...

MySQL slave library Seconds_Behind_Master delay summary

Table of contents MySQL slave library Seconds_Beh...

Detailed explanation of adding click event in echarts tooltip in Vue

Table of contents need Workaround 1. Set tooltip ...

Detailed explanation of React event binding

1. What is In react applications, event names are...

Problems and solutions for MYSQL5.7.17 connection failure under MAC

The problem that MYSQL5.7.17 cannot connect under...