vue+django实现一对一聊天功能的实例代码


Posted in Javascript onJuly 17, 2019

vue+django实现一对一聊天和消息推送的功能。主要是通过websocket,由于Django不支持websocket,所以我使用了django-channels。考虑到存储量的问题,我并没有把聊天信息存入数据库,服务端的作用相当于一个中转站。我只讲述实现功能的结构性代码,具体的实现还请大家看源代码。

前端聊天界面

前端消息提醒界面

后端代码

效果展示

vue+django实现一对一聊天功能的实例代码

实现过程

后端

首先,我们需要先定义websocket的两条连接路径。ws/chat/xxx/(xxx指代聊天组)这条路径是当聊天双方都进入同一个聊天组以后,开始聊天的路径。push/xxx/(xxx指代用户名)这条是指当有一方不在聊天组,另一方的消息将通过这条路径推送给对方。ws/chat/xxx/只有双方都进入聊天组以后才开启,而push/xxx/是自用户登录以后,直至退出都开启的。

websocket_urlpatterns = [
 url(r'^ws/chat/(?P<group_name>[^/]+)/$', consumers.ChatConsumer),
 url(r'^push/(?P<username>[0-9a-z]+)/$', consumers.PushConsumer),
]

我们采用user_a的id加上下划线_加上user_b的id的方式来命名聊天组名。其中id值从小到大放置,例如:195752_748418。当用户通过ws/chat/group_name/的方式向服务端请求连接时,后端会把这个聊天组的信息放入一个字典里。当连接关闭时,就把聊天组从字典里移除。

class ChatConsumer(AsyncJsonWebsocketConsumer):
 chats = dict()
 async def connect(self):
 self.group_name = self.scope['url_route']['kwargs']['group_name']
 await self.channel_layer.group_add(self.group_name, self.channel_name)
 # 将用户添加至聊天组信息chats中
 try:
  ChatConsumer.chats[self.group_name].add(self)
 except:
  ChatConsumer.chats[self.group_name] = set([self])
 #print(ChatConsumer.chats)
 # 创建连接时调用
 await self.accept()
 async def disconnect(self, close_code):
 # 连接关闭时调用
 # 将关闭的连接从群组中移除
 await self.channel_layer.group_discard(self.group_name, self.channel_name)
 # 将该客户端移除聊天组连接信息
 ChatConsumer.chats[self.group_name].remove(self)
 await self.close()

接着,我们需要判断连接这个聊天组的用户个数。当有两个用户连接这个聊天组时,我们就直接向这个聊天组发送信息。当只有一个用户连接这个聊天组时,我们就通过push/xxx/把信息发给接收方。

async def receive_json(self, message, **kwargs):
 # 收到信息时调用
 to_user = message.get('to_user')
 # 信息发送
 length = len(ChatConsumer.chats[self.group_name])
 if length == 2:
  await self.channel_layer.group_send(
  self.group_name,
  {
   "type": "chat.message",
   "message": message.get('message'),
  },
  )
 else:
  await self.channel_layer.group_send(
  to_user,
  {
   "type": "push.message",
   "event": {'message': message.get('message'), 'group': self.group_name}
  },
  )
 async def chat_message(self, event):
 # Handles the "chat.message" event when it's sent to us.
 await self.send_json({
  "message": event["message"],
 })
# 推送consumer
class PushConsumer(AsyncWebsocketConsumer):
 async def connect(self):
 self.group_name = self.scope['url_route']['kwargs']['username']
 await self.channel_layer.group_add(
  self.group_name,
  self.channel_name
 )
 await self.accept()
 async def disconnect(self, close_code):
 await self.channel_layer.group_discard(
  self.group_name,
  self.channel_name
 )
 # print(PushConsumer.chats)
 async def push_message(self, event):
 print(event)
 await self.send(text_data=json.dumps({
  "event": event['event']
 }))

前端

前端实现websocket就比较简单了。就是对websocket进行初始化,定义当websocket连接、关闭和接收消息时要执行哪些动作。

<script>
 export default {
 name : 'test',
 data() {
 return {
 websock: null,
 }
 },
 created() {
 this.initWebSocket();
 },
 destroyed() {
 this.websock.close() //离开路由之后断开websocket连接
 },
 methods: {
 initWebSocket(){ //初始化weosocket
 const wsuri = "ws://127.0.0.1:8080";
 this.websock = new WebSocket(wsuri);
 this.websock.onmessage = this.websocketonmessage;
 this.websock.onopen = this.websocketonopen;
 this.websock.onerror = this.websocketonerror;
 this.websock.onclose = this.websocketclose;
 },
 websocketonopen(){ //连接建立之后执行send方法发送数据
 let actions = {"test":"12345"};
 this.websocketsend(JSON.stringify(actions));
 },
 websocketonerror(){//连接建立失败重连
 this.initWebSocket();
 },
 websocketonmessage(e){ //数据接收
 const redata = JSON.parse(e.data);
 },
 websocketsend(Data){//数据发送
 this.websock.send(Data);
 },
 websocketclose(e){ //关闭
 console.log('断开连接',e);
 },
 },
 }
</script>

参考文章

Django Channels 实现点对点实时聊天和消息推送

Vue中使用websocket的正确使用方法

总结

以上所述是小编给大家介绍的vue+django实现一对一聊天功能的实例代码,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对三水点靠木网站的支持!
如果你觉得本文对你有帮助,欢迎转载,烦请注明出处,谢谢!

Javascript 相关文章推荐
js 动态文字滚动的例子
Jan 17 Javascript
showModalDialog在谷歌浏览器下会返回Null的解决方法
Nov 27 Javascript
JavaScript的React框架中的JSX语法学习入门教程
Mar 05 Javascript
JS调用Android、Ios原生控件
Jan 06 Javascript
JS分页的实现(同步与异步)
Sep 16 Javascript
js判断传入时间和当前时间大小实例(超简单)
Jan 11 Javascript
React中的render何时执行过程
Apr 13 Javascript
在 vue-cli v3.0 中使用 SCSS/SASS的方法
Jun 14 Javascript
微信小程序下拉框功能的实例代码
Nov 06 Javascript
vue-cli2与vue-cli3在一台电脑共存的实现方法
Sep 25 Javascript
VUE table表格动态添加一列数据,新增的这些数据不可以编辑(v-model绑定的数据不能实时更新)
Apr 03 Javascript
JS实现纸牌发牌动画
Jan 19 Javascript
微信小程序从注册账号到上架(图文详解)
Jul 17 #Javascript
js设置默认时间跨度过程详解
Jul 17 #Javascript
Vue 前端实现登陆拦截及axios 拦截器的使用
Jul 17 #Javascript
初试vue-cli使用HBuilderx打包app的坑
Jul 17 #Javascript
移动端吸顶fixbar的解决方案详解
Jul 17 #Javascript
基于webpack4+vue-cli3项目实现换肤功能
Jul 17 #Javascript
js getBoundingClientRect使用方法详解
Jul 17 #Javascript
You might like
简单的页面缓冲技术
2006/10/09 PHP
PHP初学入门
2006/11/19 PHP
同一空间绑定多个域名而实现访问不同页面的PHP代码
2006/12/06 PHP
php使用异或实现的加密解密实例
2013/09/04 PHP
PHP快速排序算法实现的原理及代码详解
2019/04/03 PHP
PHP大文件切割上传并带进度条功能示例
2019/07/01 PHP
jQuery $.each的用法说明
2010/03/22 Javascript
基于jquery的15款幻灯片插件
2011/04/10 Javascript
js写的评论分页(还不错)
2013/12/23 Javascript
关闭时刷新父窗口两种方法
2014/05/07 Javascript
使用jquery.upload.js实现异步上传示例代码
2014/07/29 Javascript
Nodejs+express+html5 实现拖拽上传
2014/08/08 NodeJs
简单总结JavaScript中的String字符串类型
2016/05/26 Javascript
javascript内存分配原理实例分析
2017/04/10 Javascript
使用 Vue.js 仿百度搜索框的实例代码
2017/05/09 Javascript
浅谈nodejs中的类定义和继承的套路
2017/07/26 NodeJs
VUE2 前端实现 静态二级省市联动选择select的示例
2018/02/09 Javascript
vue.js数据绑定操作详解
2018/04/23 Javascript
JS数组去重的6种方法完整实例
2018/12/08 Javascript
如何为你的JavaScript代码日志着色详解
2019/04/08 Javascript
Vue Element UI + OSS实现上传文件功能
2019/07/31 Javascript
vue 路由子组件created和mounted不起作用的解决方法
2019/11/05 Javascript
toString.call()通用的判断数据类型方法示例
2020/08/28 Javascript
vue项目打包后提交到git上为什么没有dist这个文件的解决方法
2020/09/16 Javascript
python中的多线程实例教程
2014/08/27 Python
python简单猜数游戏实例
2015/07/09 Python
pycharm下打开、执行并调试scrapy爬虫程序的方法
2017/11/29 Python
Python中使用pypdf2合并、分割、加密pdf文件的代码详解
2019/05/21 Python
Python面向对象之继承原理与用法案例分析
2019/12/31 Python
PyQT5 实现快捷键复制表格数据的方法示例
2020/06/19 Python
浅析Python面向对象编程
2020/07/10 Python
python中time、datetime模块的使用
2020/12/14 Python
微信浏览器左上角返回按钮拦截功能
2017/11/21 HTML / CSS
一套Delphi的笔试题一
2016/02/14 面试题
中班下学期个人总结
2015/02/12 职场文书
基于python定位棋子位置及识别棋子颜色
2021/07/26 Python