您的位置:首页技术文章
文章详情页

Vue实现聊天界面

【字号: 日期:2022-09-28 15:19:59浏览:22作者:猪猪

本文实例为大家分享了Vue实现聊天界面展示的具体代码,供大家参考,具体内容如下

1.功能需求

根据索引选择跟不同的人进行聊天

Vue实现聊天界面

Vue实现聊天界面

2.代码展示

mock.js:

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

userinfo.js:

let usermsg={ id:'122', imgurl:'/static/image/8.jpg', words:'是的!', data:{id:'1529',imgurl:'/static/image/7.jpg',name:'易安居士',words:[ {info:'在吗?'}, {info:'不在'}, {info:'你把草稿交了没有'}, {info:'我今天中午吃完饭 就一直看剧了'}, {info:'我发现我真的是宅女'}, {info:'哈哈哈'}, {info:'有空找你约顿饭'}, {info:'嗯嗯'}, {info:'反正影响不大'}] }}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 } ]})// 解决路由报错的代码const originalPush = Router.prototype.pushRouter.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)' 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: '微信', 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)'; // 动态dom元素渲染完成之后,跳转到另一个界面(ChatDetail) // 获取动态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>

父组件使用子组件里的属性和方法:在父组件中的子组件上定义ref属性,通过 this.$ refs.name.属性或this.$refs.name.方法

ChatChild.vue:

<template> <div id='chatchild'> <div class='photo'> <img :src='https://www.haobala.com/bcjs/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- /> </div> <div class='chattop_name'>{{name}}</div> <div class='chattop_more'><icon-svg icon- /> </div> </div> <div class='chatcontent'> <ChatMsg ref='chatmsg' /> </div> <div class='chatfooter'> <div @click='changeSound'><icon-svg :icon- /> </div> <div><input ref='sendcontent' @keypress='sendmsg' :type='istype' :value='isvalue' /> </div> <div><icon-svg icon- /> </div> <div><icon-svg icon- /> </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: { // 进行返回操作 goback() { this.$router.go(-1); }, // 切换input的类型 changeSound() { // 在data中定义一个变量isshow:false,利用this.isshow与!this.isshow进行切换 if (!this.isshow) {this.isshow = true;this.issound = 'yuyin';this.istype = 'button';this.isvalue = '按住 说话'; } else {this.isshow = false;this.issound = 'xiaoxitongzhi';this.istype = 'text';this.isvalue = ''; } }, // 发送消息 sendmsg(e) { // 1、用ref定义输入回复内容的input文本框,定义sendcontent变量接收其value值(输入的内容) let sendcontent = this.$refs.sendcontent.value; if (e.keyCode === 13 && sendcontent.split(' ').join('').length !== 0) {// 2、将ChatDetail(父)组件中的sendcontent(文本框输入的值)先用tomsg接收this.tomsg = sendcontent;// 3、用ref定义ChatMsg(子)组件,并在mounted中使用$refs获取,即this.msgchild// 4、调子组件里的方法,并将tomsg传到ChatMsg(子)组件(具体的聊天内容)中this.msgchild.saveMsg(this.tomsg);// 5、发送完一条信息之后,需清空文本框this.$refs.sendcontent.value = '';// 回车时,调用子组件的随机消息的方法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 ref='msg'> <!-- 动态创建 --> <div v-for='(item,index) in lists' :key='index'> <div v-if='item.id==122' class='user'><div v-scroll> <img :src='https://www.haobala.com/bcjs/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='https://www.haobala.com/bcjs/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自动滚动到底部 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.目录结构

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持好吧啦网。

标签: Vue
相关文章: