推送V3 - Vue + Layim + Websocket 实践笔记
Vue + Layim 实践笔记
坦白讲,我接触的前端很少,不喜欢在自己不擅长的地方搞来搞去,Vue中集成了Layim的人工客服Im系统,
出发点是挑战一下自己,经历了将近2个月的时间,项目一波三折,实属不易。
两者的区别
Vue的编程模式MVVM,没有Dom的概念,全局都是针对模型数据进行的操作,有固定的生命周期和路由。
Layim是layUi中的一个组件,是个类似QQ的Im通信工具模板。
实践
1.vue 结构
.
├── build
├── config
│ ├── test1.env.js
│ └── test.env.js
├── index.html
├── package.json
├── README.md
├── robots.txt
├── src
│ ├── App.vue
│ ├── components
│ ├── main.js
│ ├── pages
│ └── router
├── static
│ ├── layim
└── test├── e2e└── unit
step 01.引入js文件
用到的Js或者是css文件 在index.html根目录直接引入就可以
<script src="/static/layim/src/layui.js"></script>
<link rel="stylesheet" href="https://unpkg.com/element-ui@2.9.1/lib/theme-chalk/index.css">
step 02.initjs 配置
import complaint from './_complaint';
import channel from './_channel';
let pages = [//...complaint,channel
];
step 03.新建路由
路由js中,路由的Name是 customerLists、customerChatLists,folderName名字拼上pages的key值。
export default {folderName: 'customer',pages: {Lists: {title: '客服管理',path: '/customer/Lists'},ChatLists: {title: '聊天记录',path: '/customer/ChatLists'},Console: {title: '控制台',path: '/customer/Console'}}
}
Vue 生命周期
beforeCreate -> reated -> beforeMount -> mounted -> beforeUpdate -> updated -> activated -> deactivated -> beforeDestroy -> destroyed
Vue的生命周期就是一个执行过程,在指定的生命内执行相对应的函数
实践
1.新页面跳转在客服列表中选取一个按钮跳转到自己的控制台,代码如下:
{title: '控制台',width: 200,type: 'handle',btn: {manager: {text: '控制台',handle: this.managerHandle}},width: 140
},
跳转方法:
managerHandle(row){this.$router.push({name: 'customerConsole', params: { manager_id: row.manager_id,virtual_uid:row.virtual_uid }})
}
2.控制台页面 Console.vue
在index.html里引入layim.js成功后,其实Js已经引入成功,需要两步初始化Layim的界面。
- create 方法里接收刚才传递的参数,根据不用的客服ID初始化不用的数据。
created(){let params = this.$route.paramsthis.$data.virtual_uid = params.virtual_uid;this.$data.manager_id = params.manager_id;
},
- 挂载方法里写layim的需要的业务代码
//getMessage接收消息
//sendMessage发送消息mounted(){layui.use('layim', (layim) => {//1 实例化websocketthis.websocket = new WebSocket(wsuri);//2.websocket open方法this.websocket.onopen = (event) => {//...}//3.webscoket接收消息的方法this.websocket.onmessage = (event) => {//getMessage接收消息layim.getMessage({username: responseData.body.username,avatar: responseData.body.avatar,id: responseData.body.to_uid,type: "friend",content: responseData.body.contents});}//4.websocket关闭方法this.websocket.onclose = (event) => {//...}//5.websocket 错误方法this.websocket.onerror = (event) => {//...}layim.on('sendMessage', (data)=>{var to_uid = data.to.id;var contents = data.mine.content;var msgData = '{"client_type":5,"msg_type":19,"syncstamp":"'+ Date.parse(new Date()) +'","body":{"to_uid":"'+to_uid+'","contents":"'+ contents+'"}}';if ( this.websocket.readyState == 1 ) {this.websocket.send(msgData);}}}
}
3.切换Tab时隐藏和刷新
在Layim使用的过程中使用外部加载Layim,它的Dom结构单独存在,不属于Vue中,所以当切换Tab页就需要隐藏和显示Layim的html结构实体。
watch:{$route(route) {var layimDom = this.getLayim();if(layimDom != null){if(route.name == 'customerConsole' || route.name == 'ChatLists' ){let params = this.$route.paramsif( params.virtual_uid ){this.$data.virtual_uid = params.virtual_uid;this.$data.manager_id = params.manager_id;layui.use('layim', (layim) => {// 清空好友分组数据缓存this.$destroy();this.initLayim(layim,initMessage);});}layimDom.removeAttribute('hidden');}else{layimDom.setAttribute('hidden',true);}}}
},
在多个客服人员切换Tab初始化时,this.$destroy();
方法很关键,在这里有一个坑,在Layim重新请求新的接口,但是Layim依然不会初始化数据,销毁了变量才会重新初始化数据。
4.添加右键菜单
路径: static/layim/src/lay/modules/layim.js
,代码如下,
/* 绑定好友右击事件 */
$('body').on('mousedown', '.layim-list-friend li ul li', function(e){// 清空所有右击弹框emptyTips();if(3 != e.which) {return;}// 不再派发事件e.stopPropagation();var othis = $(this);if (othis.hasClass('layim-null')) return;// 移除所有选中的样式$('.layim-list-friend li ul li').removeAttr("style","");// 标注为选中othis.css({'background-color':'rgba(0,0,0,.05)'});var id = $(this).data('id');var im_rid = $(this).data('rid');var uid = Date.now().toString(36);var im_top = $(this).data('top');var im_flag= $(this).data('flag');var space_icon = ' ';var space_text = ' ';console.log(im_flag,im_top);var top_text = im_top == 2 ? '已经置顶' : '置顶会话';var flag_text = '标记会话';if(im_top == 2){var disabled = 'layui-btn-disabled';}else{var disabled = '';}var html = ['<ul id="contextmenu_'+id + '" data-top="'+im_top+'" data-flag="'+im_flag+'" data-id="'+id+'" data-rid="'+im_rid+'" data-mold="1">','<li data-type="menuTop" class="'+disabled+'" ><i class="layui-icon" ></i>'+space_icon+top_text+'</li>','<li data-type="menuFlag"><i class="layui-icon"></i>'+space_icon+flag_text +'</li>','<li data-type="menuDel"><i class="layui-icon" ></i>'+space_icon+'删除好友</li></ul>',].join('');layer.tips(html, othis, {tips: 1,time: 0,shift: 5,fix: true,skin: 'ayui-box layui-layim-contextmenu',success: function(layero){var liCount = (html.split('</li>')).length;var stopmp = function (e) { stope(e); };layero.off('mousedowm',stopmp).on('mousedowm',stopmp);var layerobj = $('#contextmenu_'+id).parents('.layui-layim-contextmenu');// 移动弹框位置var top = layerobj.css('top').toLowerCase().replace('px','');var left = layerobj.css('left').toLowerCase().replace('px','');top = getTipTop(1, top, liCount);left = 30 + parseInt(left);layerobj.css({'width':'150px', 'left':left+'px', 'top':top+'px'});$('.layui-layim-contextmenu li').css({'padding-left':'18px'});}});
});
- 对菜单上的事件做处理
置顶事件,参考代码:
menuTop: function(){var uid = $(this).parent().data('id');var rid = $(this).parent().data('rid');var im_top = $(this).parent().data('top');var top = im_top == 1 ? 2 : 1;var data = {"id":uid,"im_rid":rid,"im_top":top};$.ajax({url: '/api/customer/setcustomertop',type: "GET",data: data,dataType: 'json',success: function(res){topList({type: 'friend' //或者group,id: uid //好友或者群组ID});},error:function(res){}});},
标记事件,参考代码:
menuFlag: function(){var uid = $(this).parent().data('id');var rid = $(this).parent().data('rid');var im_flag = $(this).parent().data('flag');var flag = im_flag == 1 ? 2 : 1;var data = {"id":uid,"im_rid":rid,"im_flag":flag};$.ajax({url: '/customer/setcustomerflag',type: "GET",data: data,dataType: 'json',success: function(res){flagList({type: 'friend' //或者group,id: uid //好友或者群组ID,flag:res.data.im_flag});},error:function(res){console.log(res);}});},
Ajax成功后返回的Dom操作:
- 置顶,把当前行的li移动到最第一个元素的位置,更新缓存,更新缓存的一步很重要。
var topList = function(data){var listElem = layimMain.find('.layim-list-'+ data.type);var obj = {};var html = '';if(cache[data.type]){if(data.type === 'friend'){layui.each(cache.friend, function(index1, item1){layui.each(item1.list, function(index, item){if(data.id == item.id){var li = listElem.find('>li').eq(index1);var list = li.find('.layui-layim-list>li');var ul = listElem.find('.layui-layim-list');li.find('.layui-layim-list>li').eq(index).attr('data-top',2);html += li.find('.layui-layim-list>li').eq(index).prop("outerHTML");li.find('.layui-layim-list>li').eq(index).remove();//从cache的friend里面也删除掉好友//console.log(html,item);ul.prepend(html);var arrTop = cache.friend[index1].list[index];arrTop.im_top = 2;cache.friend[index1].list.splice(index, 1);cache.friend[index1].list.unshift(arrTop);return friend = true;}});});}}}
遇到了很多坑,终于凑合着完成了…
推送V3 - Vue + Layim + Websocket 实践笔记相关推荐
- flux服务器推消息,服务端主动推送数据,除了 WebSocket 你还能想到啥?
原标题:服务端主动推送数据,除了 WebSocket 你还能想到啥? 来自公众号: 江南一点雨 在 上篇文章 中,松哥和大家分享了 WebFlux 的基本用法,小伙伴们已经了解到使用 WebFlux ...
- websocket文档_WebSocket推送 原理扫盲到上手实践
关于服务端推送技术,大家比较熟悉的可能就是轮询,但是轮询只能是由客户端先发起http请求.在HTTP1.1中的keep-alive方式建立的http连接,但是一个Request只能对应一个Respon ...
- 服务端主动推送数据,除了 WebSocket 你还能想到啥?
在上篇文章中,松哥和大家分享了 WebFlux 的基本用法,小伙伴们已经了解到使用 WebFlux 我们的返回值可以是 Mono 也可以是 Flux,如果是 Flux,由于 Flux 中包含多个元素, ...
- 极光API推送 (v3 版本)
Push API v3 这是 Push API 最近的版本. 相比于 API v2 版本,v3 版本的改进为: 完全基于 https,不再提供 http 访问: 使用 HTTP Basic Authe ...
- java socket 推送机制_Java中websocket消息推送的实现代码
一.服务层 package com.demo.websocket; import java.io.IOException; import java.util.Iterator; import java ...
- java websocket修改为同步_服务端向客户端推送消息技术之websocket的介绍
websocket的介绍 在讲解WebSocket前,我们先来看看下面这种场景,在HTTP协议下,怎么实现. 需求: 在网站中,要实现简单的聊天,这种情况怎么实现呢?如下图: 当发送私信的时候,如 ...
- php socket主动推送消息,PHP使用WebSocket主动推送【微信小程序接收】
WebSocket.jpeg Websocket是一种服务端和客户端可以持久连接的通信协议,我们可以利用WebSocket的特性实现服务器主动向客户端推送消息的功能. 这里我们用TP5.1框架结合Wo ...
- 物联网设备数据流转之数据如何实时推送至前端:WebSocket服务端推送
背景 还记得,我们在物联网设备数据流转之实时数据从哪里来.如何转发:Node.js, MQTT, EMQX的WebHook这篇文章中,当 EMQX 的 WebHook 收到来自设备的消息时,我们当时只 ...
- 物联网设备数据流转之数据如何实时推送至前端:WebSocket前端接收
背景 在实现 WebSocket 前端接收前,我们先说明白一件事,为什么要使用WebSocket? 这要从 HTTP 协议说起,我们知道 HTTP 协议只能由客户端发起,而且是短链接,这就会导致我们在 ...
- 通过容器提交镜像(docker commit)以及推送镜像(docker push)笔记
在本地创建一个容器后,可以依据这个容器创建本地镜像,并可把这个镜像推送到Docker hub中,以便在网络上下载使用. 查看镜像 [root@docker-test1 ~]# docker image ...
最新文章
- svg图片怎么存手机上_一张普通的图片,是怎么让安卓手机死机的?
- java多态上转下_(转)java的多态(向上转型、向下转型)
- C# Winform小程序:局域网设置NTP服务器、实现时间同步
- linux下如何修改weblogic console登陆的用户名和密码
- Tricks with Direct Memory Access in Java
- 基于Jekyll的博客模板
- 解决 sublime text 3 there are no packages available for installation 错误
- NioEventLoopGroup 源码分析
- 聪聪用计算机计算235乘49,四年级数学题库
- 换协议、改代码,Elastic要逼开发者二选一?
- 软件测试自我评价模版,软件测试简历自我评价填写样本
- 【ZBrush笔刷】实用笔刷和Alpah下载,及笔刷使用方法
- 十六进制和二进制相互转换(快速转换)
- 计算机键入命令,Win7系统安装软件提示命令行语法错误键入“ 命令/?”怎么办...
- 王强 河南大学计算机学院,王强-河南大学生命科学学院
- jena mysql_使用Jena将本体存入MySQL
- 英文版xp系统下载ghost xp sp3英文版(双语纯净版、可随意转换)
- html相册制作成视频,怎么把照片制作成视频,视频相册制作免费软件|特效多多
- 欧拉回路(欧拉路径)
- bugku_托马斯.杰斐逊解题报告
热门文章
- 从木桶理论看自身职业生涯规划
- vue slideup_像jQuery的slideUp / slideDown一样,但是对于Vue
- Intel RDT特性详解
- 自学报告:创新设计思维
- 大战略游戏:统治者:罗马 for Mac
- Python 实战 | 工欲善其事,必先利其器
- [游戏安全] Unity3D游戏无意中的发现
- [ - OpenGLES3.0 - ] 第一集 主线 - 打开新世界的大门
- Ubuntu下制作.deb安装包之dkpg
- SVN E200030: There are unfinished transactions detected