日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区

您的位置:首頁技術文章
文章詳情頁

vue實現web在線聊天功能

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

本文實例為大家分享了vue實現web在線聊天的具體代碼,供大家參考,具體內容如下

最終實現的效果

vue實現web在線聊天功能

實現過程

無限滾動窗體的實現之前已經介紹過,這里就不在贅述了,不清楚的可以通過文檔前文的傳送門進行查看。

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

話不多說,直接上代碼

后端返回數據格式

我覺得所有的設計和功能實現都是基于數據的基礎上去實現的,所以咋們先來看一下后端返回的數據格式:

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

這里需要說明的是,content字段返回的是一個json格式的字符串數據,content內容格式如下:

// 文本消息{ 'type': 'txt', 'msg':'你好' //消息內容}

// 圖片消息{ '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':'中國 浙江省 杭州市 網商路 599號', //地理位置 'longitude':120.1908686708565,// 經度 '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://m.b3g6.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='主動一點,世界會更大!':rows='4' /> </div> <div class='footer-btn'><Button @click='cancel' type='text'>取消</Button><Button type='primary' @click='sendMsg'>發送</Button> </div> </Modal></template>

注:自己發的信息和別人發的信息展示樣式不一樣,所以需要通過isOneself字段進行展示樣式的區分。

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’), // 后端沒有返回頭像默認頭像,注意:需要用require請求方式才能動態訪問本地文件 data:[], distincData:[], // 消息去重數組 offsetMax:0, // 最大偏移位,記錄當前獲取的最大id,往后的定時輪詢數據時每次只獲取比這個id大的數據 offsetMin:0, // 最小偏移位,記錄當前獲取的最小id,往上滑動時每次只獲取比這小id大的數據 searchForm:{ // 每次定時獲取數據或首次加載數據提交的form表單數據pageNumber: 1,pageSize: 20 }, form:{ // 發送數據提交數據表單content:'',msg:'' }, timerSwitch:0 // 定時器開關,默認關閉 }; }, methods: { init(){ }, loadMsg(){ // 窗體打開默認加載一頁數據,窗體什么周期中值運行一次 let that = this; this.searchForm.offsetMax = this.offsetMax; listMsg(this.searchForm).then(res=>{if (res.code == 200) { res.data.forEach(e => { // 標記最大偏移位 if(that.offsetMax < e.msgId){that.offsetMax = e.msgId; } e.content = JSON.parse(e.content); that.data.unshift(e) that.distincData.push(e.msgId); // 標記最大偏移位,后端返回數據是逆序,所以最后一條id最新 that.offsetMin = e.msgId; }); // 數據加載完成,滾動條滾動到窗體底部 this.scrollToBottom();} }); }, show(){ // 打開窗體初始化數據 // 初始化數據 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; // 開啟定時器 this.timerSwitch = 1; this.reloadData(); }, sendMsg(){ // 發送消息 if(!this.form.msg){ this.$Message.warning('不能發送空白信息');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(); // 發送信息只返回當前一條,此時可能對方已經發送信息,所以不修改偏移量} }); }, scrollToBottom(){ // 滾動到窗體底部 this.$nextTick(()=>{ let chatform = document.getElementById('chatform'); chatform.scrollTop = chatform.scrollHeight; }); }, // 滾動到最上方,取歷史數據,根據分頁參數取。不用修改偏移標記位,但是需要判重 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(){ // 判斷定時器開關是否開啟,如果開啟,則執行定時器 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 => { // 修改最大偏移位,放到校驗重復之前,防止當前發送信息已經放入消息列表,但是偏移值沒該的情況 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);// 收到新消息,判斷高度,如果當前滾動條高度距底部小于100,則動滑到底部let chatform = document.getElementById('chatform');let gap = chatform.scrollHeight -chatform.scrollTop;if(gap >0 && gap < 400){ this.scrollToBottom();} } }); that.reloadData(); }}); },1000*2); } }, cancel(){ // 關閉窗體需要把提示任務開關一起關閉調 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>

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持好吧啦網。

標簽: Vue
相關文章:
日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区
日韩高清电影一区| 亚洲大片在线| 欧美一级精品| 91av亚洲| 狠狠操综合网| 免费观看在线综合| 国产精品香蕉| 国产乱人伦丫前精品视频 | 久久精品主播| 国产亚洲字幕| 久久精品99国产精品| 欧美日韩国产在线观看网站 | 国产成人精品一区二区免费看京 | 精品黄色一级片| 国产精品3区| 婷婷综合六月| 在线视频免费在线观看一区二区| 中文亚洲免费| 精品视频在线你懂得| 国产毛片一区| 麻豆精品在线| 欧美日韩黑人| 国产精品一区二区中文字幕| 日韩欧美一区二区三区免费观看| 国产精品试看| 精品国产午夜肉伦伦影院 | 黑丝一区二区| 天堂久久av| 极品av在线| 亚洲精品字幕| 日本aⅴ免费视频一区二区三区| 高清不卡一区| 爽好久久久欧美精品| 激情国产在线| 久久亚洲一区| 一区二区精品伦理...| 日韩中文字幕在线一区| 久久精品五月| 久久成人一区| 电影91久久久| 精品三级av在线导航| 国产精品丝袜xxxxxxx| 精品一区二区三区四区五区| 亚洲少妇自拍| 国产精选在线| 日韩精品一区第一页| 欧美日韩一二三四| 精品一区二区三区视频在线播放| 亚洲伊人精品酒店| 欧美丝袜一区| 精品久久99| 老牛国内精品亚洲成av人片| 综合一区av| 美国三级日本三级久久99| 日韩一区欧美二区| 国产毛片一区| 伊人久久婷婷| 国产精品国产三级国产在线观看| 国产精品自在| 蜜臀va亚洲va欧美va天堂 | 国产一区欧美| 新版的欧美在线视频| 国产毛片精品久久| 国产日韩亚洲| 亚洲毛片在线免费| 国产欧美日韩精品一区二区免费 | 六月婷婷一区| 国产极品一区| 欧美经典一区| 国产激情一区| 日韩av片子| 岛国av在线网站| 三上悠亚国产精品一区二区三区| 久久精品免视看国产成人| 久久黄色影视| 91精品国产乱码久久久久久久| re久久精品视频| 亚洲精品一级| 国产探花一区| 久久久久伊人| 久久视频一区| 日韩一区二区免费看| 91精品综合| 首页欧美精品中文字幕| 午夜在线精品偷拍| 日韩av中文在线观看| 国产成人免费精品| 欧美日韩国产一区精品一区| 青草av.久久免费一区| 国产一区二区久久久久| 人人爽香蕉精品| 午夜av不卡| 欧美一区自拍| 国产suv精品一区| 亚洲免费一区三区| 国产一区二区三区久久久久久久久| 亚洲特色特黄| 国产欧美日韩一级| 亚洲二区三区不卡| 亚洲久久视频| 亚洲福利一区| 福利一区二区免费视频| 日韩亚洲精品在线观看| 亚洲一区二区三区四区五区午夜 | 少妇久久久久| 国产午夜精品一区在线观看| 在线一区av| 久久不见久久见中文字幕免费| 日韩国产一区| 国产精品88久久久久久| 欧美在线日韩| 精品香蕉视频| 日韩av首页| 日韩av电影一区| 日韩欧美一区二区三区免费观看| 欧美日韩国产欧| 蜜桃av一区二区| 精品一区二区三区亚洲| 一区二区电影在线观看| 久久99高清| 蜜桃av一区| 久久99精品久久久野外观看| 亚洲一级高清| 日本欧美在线| www.com.cn成人| 亚洲综合中文| 国产精品极品| 爽好多水快深点欧美视频| 国产精品亚洲一区二区在线观看 | 国产精品视频一区二区三区| 欧美影院三区| 久久精品99久久久| 午夜欧美视频| 国产在线观看www| 国产美女亚洲精品7777| 99国产精品久久久久久久| 欧美a一区二区| 亚洲精品在线二区| 精品日韩在线| 国产精品xxxav免费视频| 日韩国产欧美一区二区三区| 免费不卡中文字幕在线| 日本а中文在线天堂| 国产精品美女在线观看直播| 在线国产一区二区| 亚洲播播91| 免费av一区| 99久久精品费精品国产| 日韩欧美三级| 日韩成人综合| 夜鲁夜鲁夜鲁视频在线播放| 欧美日韩国产免费观看视频| 欧美特黄一区| 狠狠爱成人网| 久久亚洲欧洲| 国产福利资源一区| 99精品视频在线| 宅男噜噜噜66国产日韩在线观看| 久久国产电影| 石原莉奈一区二区三区在线观看| 久久精品国产久精国产爱| 国产精品一区2区3区| 国产精品国码视频| 久久黄色影视| 婷婷成人综合| 91亚洲无吗| 精品91福利视频| 美女毛片一区二区三区四区| 首页国产欧美久久| 欧美三级第一页| 国产成人免费视频网站视频社区| 亚洲网站视频| 亚洲区第一页| 精品不卡一区| 亚洲激情社区| 欧美日韩一区二区三区在线电影| 久久高清免费| 日韩 欧美一区二区三区| 国内揄拍国内精品久久| 成人国产综合| 在线综合欧美| 亚洲黄色免费av| 午夜国产一区二区| 日韩精品一级二级| 国产欧美日韩一区二区三区四区| 高清久久一区| 视频一区二区三区在线| 国产高清视频一区二区| 国产精品av一区二区| 日韩久久一区| 91久久在线| 成人亚洲一区二区| 99pao成人国产永久免费视频 | 亚洲黄色在线| 久久国产三级| 国产精品jk白丝蜜臀av小说| 欧美久久精品一级c片| 久久精品国产999大香线蕉| 免费中文字幕日韩欧美| 国产一区精品福利|