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 = '&nbsp;&nbsp;';var space_text = '&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;';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 实践笔记相关推荐

  1. flux服务器推消息,服务端主动推送数据,除了 WebSocket 你还能想到啥?

    原标题:服务端主动推送数据,除了 WebSocket 你还能想到啥? 来自公众号: 江南一点雨 在 上篇文章 中,松哥和大家分享了 WebFlux 的基本用法,小伙伴们已经了解到使用 WebFlux ...

  2. websocket文档_WebSocket推送 原理扫盲到上手实践

    关于服务端推送技术,大家比较熟悉的可能就是轮询,但是轮询只能是由客户端先发起http请求.在HTTP1.1中的keep-alive方式建立的http连接,但是一个Request只能对应一个Respon ...

  3. 服务端主动推送数据,除了 WebSocket 你还能想到啥?

    在上篇文章中,松哥和大家分享了 WebFlux 的基本用法,小伙伴们已经了解到使用 WebFlux 我们的返回值可以是 Mono 也可以是 Flux,如果是 Flux,由于 Flux 中包含多个元素, ...

  4. 极光API推送 (v3 版本)

    Push API v3 这是 Push API 最近的版本. 相比于 API v2 版本,v3 版本的改进为: 完全基于 https,不再提供 http 访问: 使用 HTTP Basic Authe ...

  5. java socket 推送机制_Java中websocket消息推送的实现代码

    一.服务层 package com.demo.websocket; import java.io.IOException; import java.util.Iterator; import java ...

  6. java websocket修改为同步_服务端向客户端推送消息技术之websocket的介绍

    websocket的介绍 在讲解WebSocket前,我们先来看看下面这种场景,在HTTP协议下,怎么实现. 需求: 在网站中,要实现简单的聊天,这种情况怎么实现呢?如下图: ​ 当发送私信的时候,如 ...

  7. php socket主动推送消息,PHP使用WebSocket主动推送【微信小程序接收】

    WebSocket.jpeg Websocket是一种服务端和客户端可以持久连接的通信协议,我们可以利用WebSocket的特性实现服务器主动向客户端推送消息的功能. 这里我们用TP5.1框架结合Wo ...

  8. 物联网设备数据流转之数据如何实时推送至前端:WebSocket服务端推送

    背景 还记得,我们在物联网设备数据流转之实时数据从哪里来.如何转发:Node.js, MQTT, EMQX的WebHook这篇文章中,当 EMQX 的 WebHook 收到来自设备的消息时,我们当时只 ...

  9. 物联网设备数据流转之数据如何实时推送至前端:WebSocket前端接收

    背景 在实现 WebSocket 前端接收前,我们先说明白一件事,为什么要使用WebSocket? 这要从 HTTP 协议说起,我们知道 HTTP 协议只能由客户端发起,而且是短链接,这就会导致我们在 ...

  10. 通过容器提交镜像(docker commit)以及推送镜像(docker push)笔记

    在本地创建一个容器后,可以依据这个容器创建本地镜像,并可把这个镜像推送到Docker hub中,以便在网络上下载使用. 查看镜像 [root@docker-test1 ~]# docker image ...

最新文章

  1. svg图片怎么存手机上_一张普通的图片,是怎么让安卓手机死机的?
  2. java多态上转下_(转)java的多态(向上转型、向下转型)
  3. C# Winform小程序:局域网设置NTP服务器、实现时间同步
  4. linux下如何修改weblogic console登陆的用户名和密码
  5. Tricks with Direct Memory Access in Java
  6. 基于Jekyll的博客模板
  7. 解决 sublime text 3 there are no packages available for installation 错误
  8. NioEventLoopGroup 源码分析
  9. 聪聪用计算机计算235乘49,四年级数学题库
  10. 换协议、改代码,Elastic要逼开发者二选一?
  11. 软件测试自我评价模版,软件测试简历自我评价填写样本
  12. 【ZBrush笔刷】实用笔刷和Alpah下载,及笔刷使用方法
  13. 十六进制和二进制相互转换(快速转换)
  14. 计算机键入命令,Win7系统安装软件提示命令行语法错误键入“ 命令/?”怎么办...
  15. 王强 河南大学计算机学院,王强-河南大学生命科学学院
  16. jena mysql_使用Jena将本体存入MySQL
  17. 英文版xp系统下载ghost xp sp3英文版(双语纯净版、可随意转换)
  18. html相册制作成视频,怎么把照片制作成视频,视频相册制作免费软件|特效多多
  19. 欧拉回路(欧拉路径)
  20. bugku_托马斯.杰斐逊解题报告

热门文章

  1. 从木桶理论看自身职业生涯规划
  2. vue slideup_像jQuery的slideUp / slideDown一样,但是对于Vue
  3. Intel RDT特性详解
  4. 自学报告:创新设计思维
  5. 大战略游戏:统治者:罗马 for Mac
  6. Python 实战 | 工欲善其事,必先利其器
  7. [游戏安全] Unity3D游戏无意中的发现
  8. [ - OpenGLES3.0 - ] 第一集 主线 - 打开新世界的大门
  9. Ubuntu下制作.deb安装包之dkpg
  10. SVN E200030: There are unfinished transactions detected