成人在线亚洲_国产日韩视频一区二区三区_久久久国产精品_99国内精品久久久久久久

您的位置:首頁技術(shù)文章
文章詳情頁

vue實(shí)現(xiàn)web在線聊天功能

瀏覽:168日期:2022-09-28 15:25:25

本文實(shí)例為大家分享了vue實(shí)現(xiàn)web在線聊天的具體代碼,供大家參考,具體內(nèi)容如下

最終實(shí)現(xiàn)的效果

vue實(shí)現(xiàn)web在線聊天功能

實(shí)現(xiàn)過程

無限滾動(dòng)窗體的實(shí)現(xiàn)之前已經(jīng)介紹過,這里就不在贅述了,不清楚的可以通過文檔前文的傳送門進(jìn)行查看。

實(shí)時(shí)在線聊天主要功能點(diǎn) 滾動(dòng)到兩天窗體頂部,自動(dòng)加載歷史跟多信息,數(shù)據(jù)加載的時(shí)候,需要有一個(gè)loading動(dòng)畫; 發(fā)送信息是滾動(dòng)條自動(dòng)滑動(dòng)到窗體底部,并且自己發(fā)送的信息出現(xiàn)在聊天窗體中; 收到別人發(fā)送信息時(shí),需要判斷滾動(dòng)條處于窗體中的位置,在距離底部一定范圍內(nèi)收到信息需要自動(dòng)滑動(dòng)到窗體底部; 收發(fā)的信息在聊天狀態(tài)不能重復(fù)顯示; 收發(fā)的信息在聊天窗體中需要以逆序的方式展示,即離窗體底部越近的信息為最新消息; 授信最好通過WebSocket與后端建立長連接,有新消息由后端主動(dòng)向前端推送消息方式實(shí)現(xiàn),這里主要介紹前端實(shí)現(xiàn)聊天窗體思路,WebSocket部分就不展開了,采用定時(shí)器輪詢的方式簡單實(shí)現(xiàn)。

話不多說,直接上代碼

后端返回?cái)?shù)據(jù)格式

我覺得所有的設(shè)計(jì)和功能實(shí)現(xiàn)都是基于數(shù)據(jù)的基礎(chǔ)上去實(shí)現(xiàn)的,所以咋們先來看一下后端返回的數(shù)據(jù)格式:

{ 'code': 200, // 響應(yīng)編碼 'msg': 'OK', // 響應(yīng)消息 'total': 1, 'sysTime': '2020-12-16 15:23:27', // 系統(tǒng)響應(yīng)時(shí)間 'data': [{ 'avatar': '', // 用戶頭像 'content': '{'type':'txt','msg':'你好!'}', // 消息內(nèi)容 'isRead': 0, // 是否已讀 'isOneself': 0, // 是否是自己發(fā)送的消息 0否,1是 'msgId': 10, // 消息ID,用來去重 'nickName': '碧海燕魚', // 用戶昵稱 'userCode': '202012162030202232' // 用戶編碼 }]}

這里需要說明的是,content字段返回的是一個(gè)json格式的字符串?dāng)?shù)據(jù),content內(nèi)容格式如下:

// 文本消息{ 'type': 'txt', 'msg':'你好' //消息內(nèi)容}

// 圖片消息{ 'type': 'img', 'url': '圖片地址', 'ext':'jpg', 'width':360, //寬 'height':480, //高 'size': 388245}

// 視頻消息{ 'type': ’video’, 'url': 'http://nimtest.nos.netease.com/cbc500e8-e19c-4b0f-834b-c32d4dc1075e', 'ext':'mp4', 'width':360, //寬 'height':480, //高 'size': 388245}

// 地理位置消息{ 'type': 'local', 'address':'中國 浙江省 杭州市 網(wǎng)商路 599號', //地理位置 'longitude':120.1908686708565,// 經(jīng)度 'latitude':30.18704515647036 // 緯度}

HTML代碼

<template> <Modal v-model='chatVisible' draggable footer-hide : @on-cancel='cancel'> <div class='chat'> <div @scroll='scroll' > <Spin v-if='loading'><Icon type='ios-loading' size=18 class='spin-icon-load'></Icon> </Spin><div dis-hover v-for='(item,index) in data' :key='index' class='message-card'> <div :class='item.isOneself == 1?’message-row-right’: ’message-row-left’'> <img :src='http://www.piao2010.com/bcjs/item.avatar?item.avatar:defualtAvatar' > <div class='message-content'> <div :style='item.isOneself == 1?’text-align:right;display: flex;flex-direction:row-reverse’:’’'>{{item.nickName}}<span class='message-time'> {{item.createTime}}</span></div> <div class='message-body'>{{item.content.msg}}</div> </div> </div> </div> </div><Inputv-model='form.msg'type='textarea' placeholder='主動(dòng)一點(diǎn),世界會(huì)更大!':rows='4' /> </div> <div class='footer-btn'><Button @click='cancel' type='text'>取消</Button><Button type='primary' @click='sendMsg'>發(fā)送</Button> </div> </Modal></template>

注:自己發(fā)的信息和別人發(fā)的信息展示樣式不一樣,所以需要通過isOneself字段進(jìn)行展示樣式的區(qū)分。

JavaScript代碼

<script>import {listMsg,sendMsg } from '@/api/index';export default { name: 'chat', props: { value: { type: Boolean, default: false } }, data() { return { chatVisible:this.value, loading:false, defualtAvatar:require(’../../assets/defult-avatar.svg’), // 后端沒有返回頭像默認(rèn)頭像,注意:需要用require請求方式才能動(dòng)態(tài)訪問本地文件 data:[], distincData:[], // 消息去重?cái)?shù)組 offsetMax:0, // 最大偏移位,記錄當(dāng)前獲取的最大id,往后的定時(shí)輪詢數(shù)據(jù)時(shí)每次只獲取比這個(gè)id大的數(shù)據(jù) offsetMin:0, // 最小偏移位,記錄當(dāng)前獲取的最小id,往上滑動(dòng)時(shí)每次只獲取比這小id大的數(shù)據(jù) searchForm:{ // 每次定時(shí)獲取數(shù)據(jù)或首次加載數(shù)據(jù)提交的form表單數(shù)據(jù)pageNumber: 1,pageSize: 20 }, form:{ // 發(fā)送數(shù)據(jù)提交數(shù)據(jù)表單content:'',msg:'' }, timerSwitch:0 // 定時(shí)器開關(guān),默認(rèn)關(guān)閉 }; }, methods: { init(){ }, loadMsg(){ // 窗體打開默認(rèn)加載一頁數(shù)據(jù),窗體什么周期中值運(yùn)行一次 let that = this; this.searchForm.offsetMax = this.offsetMax; listMsg(this.searchForm).then(res=>{if (res.code == 200) { res.data.forEach(e => { // 標(biāo)記最大偏移位 if(that.offsetMax < e.msgId){that.offsetMax = e.msgId; } e.content = JSON.parse(e.content); that.data.unshift(e) that.distincData.push(e.msgId); // 標(biāo)記最大偏移位,后端返回?cái)?shù)據(jù)是逆序,所以最后一條id最新 that.offsetMin = e.msgId; }); // 數(shù)據(jù)加載完成,滾動(dòng)條滾動(dòng)到窗體底部 this.scrollToBottom();} }); }, show(){ // 打開窗體初始化數(shù)據(jù) // 初始化數(shù)據(jù) this.data =[]; this.distincData =[]; this.offsetMax = 0; this.offsetMin = 0; this.searchForm.pageNumber = 1; this.searchForm.pageSize = 20; this.form ={content:'',msg:'' }; this.loadMsg(); this.chatVisible = true; // 開啟定時(shí)器 this.timerSwitch = 1; this.reloadData(); }, sendMsg(){ // 發(fā)送消息 if(!this.form.msg){ this.$Message.warning('不能發(fā)送空白信息');return; } let content = { // 封裝消息體type:'txt',msg:this.form.msg }; this.form.content = JSON.stringify(content); sendOrderMsg(this.form).then(res=>{if (res.code == 200) { res.data.content = JSON.parse(res.data.content); this.data.push(res.data) this.form.msg=''; this.distincData.push(res.data.msgId); this.scrollToBottom(); // 發(fā)送信息只返回當(dāng)前一條,此時(shí)可能對方已經(jīng)發(fā)送信息,所以不修改偏移量} }); }, scrollToBottom(){ // 滾動(dòng)到窗體底部 this.$nextTick(()=>{ let chatform = document.getElementById('chatform'); chatform.scrollTop = chatform.scrollHeight; }); }, // 滾動(dòng)到最上方,取歷史數(shù)據(jù),根據(jù)分頁參數(shù)取。不用修改偏移標(biāo)記位,但是需要判重 scroll(){ let chatform = document.getElementById('chatform'); let scrollTop = chatform.scrollTop; if(scrollTop == 0){this.loading =true;let that = this;this.searchForm.offsetMin = this.offsetMin;this.searchForm.offsetMax = '';listMsgByOrder(this.searchForm).then(res=>{ this.loading =false; if (res.code == 200) { res.data.forEach(e => {if(that.distincData.indexOf(e.msgId) <0){ e.content = JSON.parse(e.content); that.data.unshift(e); that.distincData.push(e.msgId); // 修改最小偏移位 if(that.offsetMin > e.msgId){ that.offsetMin = e.msgId; }} }); }}); } }, reloadData(){ // 判斷定時(shí)器開關(guān)是否開啟,如果開啟,則執(zhí)行定時(shí)器 if(this.timerSwitch){ setTimeout(() => {let params = {};params.pageNumber = 1;params.pageSize = 20;params.offsetMax = this.offsetMax;let that = this;listMsgByOrder(params).then(res=>{ if (res.code == 200) { res.data.forEach(e => { // 修改最大偏移位,放到校驗(yàn)重復(fù)之前,防止當(dāng)前發(fā)送信息已經(jīng)放入消息列表,但是偏移值沒該的情況 if(that.offsetMax < e.msgId){ that.offsetMax = e.msgId; } if(that.distincData.indexOf(e.msgId) <0){e.content = JSON.parse(e.content);that.data.push(e)that.distincData.push(e.msgId);// 收到新消息,判斷高度,如果當(dāng)前滾動(dòng)條高度距底部小于100,則動(dòng)滑到底部let chatform = document.getElementById('chatform');let gap = chatform.scrollHeight -chatform.scrollTop;if(gap >0 && gap < 400){ this.scrollToBottom();} } }); that.reloadData(); }}); },1000*2); } }, cancel(){ // 關(guān)閉窗體需要把提示任務(wù)開關(guān)一起關(guān)閉調(diào) this.chatVisible = false; this.timerSwitch = 0; } }, mounted() { }};</script>

CSS代碼

<style lang='less'> .message {height: 350px; } .ivu-card-body { padding:5px; } .ivu-modal-body{ padding: 0px 16px 16px 16px; } .chat-message-body { background-color:#F8F8F6; width:545px; height: 350px; overflow: auto; } .message-card { margin:5px; } .message-row-left { display: flex; flex-direction:row; } .message-row-right { display: flex; flex-direction:row-reverse; } .message-content { margin:-5px 5px 5px 5px; display: flex; flex-direction:column; } .message-body { border:1px solid #D9DAD9; padding:5px; border-radius:3px; background-color:#FFF; } .message-time { margin:0 5px; font-size:5px; color:#D9DAD9; } .footer-btn { float:right; margin-bottom: 5px; } .spin-icon-load { animation:ani-spin 1s linear infinite; } @keyframes ani-spin{ form{transform: rotate(0deg);} 50% {transform: rotate(180deg);} to {transform: rotate(360deg);} }</style>

以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持好吧啦網(wǎng)。

標(biāo)簽: Vue
相關(guān)文章:
成人在线亚洲_国产日韩视频一区二区三区_久久久国产精品_99国内精品久久久久久久
亚洲综合色噜噜狠狠| 久久国产精品99久久久久久老狼| 喷水一区二区三区| 日韩午夜在线电影| 亚洲视频香蕉人妖| 欧美久久电影| 国产亚洲一区字幕| 成人av影视在线观看| 欧美日韩精品一区二区天天拍小说| 丝袜诱惑制服诱惑色一区在线观看| 亚洲综合日本| 亚洲精品国产品国语在线app| 伊人激情综合| 中文字幕一区二区三区av| 国内精品**久久毛片app| 国产亚洲欧洲997久久综合| 99久久婷婷国产综合精品电影| 日韩午夜小视频| 粉嫩一区二区三区性色av| 制服视频三区第一页精品| 国产主播一区二区三区| 欧美喷水一区二区| 国产麻豆91精品| 日韩写真欧美这视频| 成人午夜视频在线| 欧美v国产在线一区二区三区| 国产老妇另类xxxxx| 欧美一区二区不卡视频| 国产成人一区二区精品非洲| 日韩精品一区二区三区蜜臀| 顶级嫩模精品视频在线看| 精品区一区二区| 不卡的看片网站| 国产日韩欧美精品综合| 国产精品a久久久久| 国产精品久久久久一区二区三区 | 精品中文字幕一区二区小辣椒| 欧美挠脚心视频网站| 国产成人精品免费网站| 精品久久久久久久久久久久久久久 | 91丨国产丨九色丨pron| 国产欧美日韩在线视频| 欧美日韩一区二区国产| 亚洲乱码中文字幕综合| 久久精品国语| 精品亚洲国内自在自线福利| 精品久久一区二区三区| 国产精品二区在线| 亚洲大片免费看| 欧美影片第一页| 风间由美性色一区二区三区| 欧美国产日本韩| 一区二区不卡在线视频 午夜欧美不卡'| 亚洲国产成人tv| 欧美色图激情小说| 国产不卡在线播放| 国产精品人妖ts系列视频| 国产欧美69| 激情欧美日韩一区二区| 精品日韩欧美一区二区| 韩国一区二区三区在线观看| 亚洲国产日韩一区二区| 欧美日韩精品二区第二页| av激情综合网| 一区二区在线观看视频| 欧美三区免费完整视频在线观看| 99久久国产综合色|国产精品| 亚洲色欲色欲www| 色哟哟一区二区在线观看 | 亚洲国产高清一区| 日韩高清一区二区| 欧美成人在线直播| 亚洲看片一区| 久久国产精品一区二区| 精品国产免费久久| 一本一道久久综合狠狠老精东影业 | 久久午夜色播影院免费高清| 亚洲精华国产欧美| 国产在线精品不卡| 成人欧美一区二区三区| 欧美调教femdomvk| 91色综合久久久久婷婷| 亚洲地区一二三色| 亚洲精品一区二区三区蜜桃下载 | 精品久久久久久久久久久院品网| 99国内精品| 国产一区二区三区四区五区入口 | 制服视频三区第一页精品| 亚洲高清网站| 加勒比av一区二区| 欧美国产激情二区三区| 色88888久久久久久影院按摩| av一区二区三区黑人| 亚洲高清免费在线| 精品乱人伦小说| 久久国产精品一区二区三区四区| 成人免费毛片aaaaa**| 亚洲大尺度视频在线观看| 欧美第一区第二区| 亚洲一区观看| av电影在线观看不卡| 亚洲国产日日夜夜| 国产亚洲污的网站| 欧美在线一区二区| 韩国一区二区三区在线观看 | 亚洲精品1234| 丰满亚洲少妇av| 亚洲主播在线观看| 精品免费日韩av| 91极品视觉盛宴| 亚洲福利久久| aaa欧美大片| 久久不见久久见免费视频7 | 性色一区二区三区| 欧美高清不卡| 国产精品一二三四五| 亚洲宅男天堂在线观看无病毒| 久久久亚洲国产美女国产盗摄| 欧美性猛交xxxx乱大交退制版| 日韩视频在线播放| 99久久婷婷国产综合精品电影| 久久精品国产一区二区三区免费看 | 日韩欧美一二三四区| 久久久久久网| 亚洲激情网址| 欧美一区视频| 国产白丝网站精品污在线入口| 午夜精品福利一区二区三区av | 精品制服美女久久| 亚洲va天堂va国产va久| 国产精品乱码人人做人人爱| 日韩午夜电影av| 欧美在线色视频| 国产欧美日韩一区二区三区在线| 欧美在线亚洲综合一区| 国产精品资源站在线| 日韩精品电影在线| 一二三四社区欧美黄| 国产精品久久久久久久午夜片| 精品欧美久久久| 在线综合+亚洲+欧美中文字幕| 久久久久久久欧美精品| 一本久久综合| 永久91嫩草亚洲精品人人| 欧美一区二区三区在线播放| 成人一区二区三区视频在线观看| 久久精品国产亚洲a| 亚洲高清视频中文字幕| 亚洲激情校园春色| 日韩理论片一区二区| 欧美经典三级视频一区二区三区| 欧美精品一区二区三区四区| 欧美一二三四区在线| 在线成人高清不卡| 在线亚洲欧美专区二区| 久久精品一区| 国产欧美日韩伦理| 亚洲激情视频| 亚洲国产精品第一区二区三区| 国产综合精品| 欧美女人交a| 欧美1区2区3区| 99久久久国产精品| gogogo免费视频观看亚洲一| 国产69精品久久99不卡| 国产精品一品二品| 国产精品一区三区| 国产高清成人在线| 国产精品资源网| 国产高清无密码一区二区三区| 国产老女人精品毛片久久| 国产一区二区不卡在线| 国产一区二区三区在线观看免费 | 欧美综合在线视频| 日本电影欧美片| 精品1区2区3区| 欧美日韩一区二区在线观看 | 欧美福利视频导航| 在线日韩一区二区| 欧美日韩情趣电影| 欧美二区乱c少妇| 欧美高清视频www夜色资源网| 日韩一级大片在线观看| 欧美mv日韩mv| 精品成人私密视频| 久久久久国产精品人| 国产亚洲欧美日韩俺去了| 国产婷婷色一区二区三区| 国产人成一区二区三区影院| 国产午夜精品在线观看| 国产亚洲一区二区三区| 国产精品理论片在线观看| 国产精品国产三级国产普通话三级 | 国产一区二区精品久久91| 国产成人免费视频一区| 99精品视频在线免费观看| 国产在线成人| 亚洲自啪免费| 欧美精品色综合| 欧美精品一区男女天堂|