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 相关文章推荐
jQuery 研究心得 取得属性的值
Nov 30 Javascript
实现web打印的各种方法介绍及实现代码
Jan 09 Javascript
JavaScript中的null和undefined区别介绍
Jan 01 Javascript
jQuery选择器之基本选择器与层次选择器
Mar 03 Javascript
简介BootStrap model弹出框的使用
Apr 27 Javascript
JS实现简单易用的手机端浮动窗口显示效果
Sep 07 Javascript
js与jquery分别实现tab标签页功能的方法
Nov 18 Javascript
微信小程序 支付简单实例及注意事项
Jan 06 Javascript
js弹性势能动画之抛物线运动实例详解
Jul 27 Javascript
Vue.js实现价格计算器功能
Mar 30 Javascript
JS库之Highlight.js的用法详解
Sep 13 Javascript
vue下载二进制流图片操作
Oct 26 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
PHP中查询SQL Server或Sybase时TEXT字段被截断的解决方法
2009/03/10 PHP
php使用fopen创建utf8编码文件的方法
2014/10/31 PHP
php实现的css文件背景图片下载器代码
2014/11/11 PHP
PHP概率计算函数汇总
2015/09/13 PHP
PHP实现长文章分页实例代码(附源码)
2016/02/03 PHP
PHP 无限级分类
2017/05/04 PHP
讲两件事:1.this指针的用法小探. 2.ie的attachEvent和firefox的addEventListener在事件处理上的区别
2007/04/12 Javascript
jquery 指南/入门基础
2007/11/30 Javascript
复选框全选与全不选操作实现思路
2013/08/18 Javascript
jQuery的css()方法用法实例
2014/12/24 Javascript
javascript鼠标滑过显示二级菜单特效
2020/11/18 Javascript
JS常用算法实现代码
2016/11/14 Javascript
bootstrap multiselect下拉列表功能
2017/08/22 Javascript
vue 数组和对象不能直接赋值情况和解决方法(推荐)
2017/10/25 Javascript
vue 项目 iOS WKWebView 加载
2019/04/17 Javascript
Node 搭建一个静态资源服务器的实现
2019/05/20 Javascript
探索JavaScript中私有成员的相关知识
2019/06/13 Javascript
es6 for循环中let和var区别详解
2020/01/12 Javascript
JavaScript函数柯里化实现原理及过程
2020/12/02 Javascript
[02:12]DOTA2英雄基础教程 变体精灵
2013/12/16 DOTA
python 统计代码行数简单实例
2017/05/04 Python
python通过pip更新所有已安装的包实现方法
2017/05/19 Python
详解python中的文件与目录操作
2017/07/11 Python
浅谈flask中的before_request与after_request
2018/01/20 Python
使用keras根据层名称来初始化网络
2020/05/21 Python
基于python实现查询ip地址来源
2020/06/02 Python
加拿大购物频道:The Shopping Channel
2016/07/21 全球购物
美国著名的团购网站:Woot
2016/08/02 全球购物
Myprotein瑞士官方网站:运动营养和健身网上商店
2019/09/25 全球购物
自荐信格式
2013/12/01 职场文书
小学教师师德感言
2014/02/10 职场文书
向国旗敬礼学生寄语大全
2014/09/30 职场文书
2014镇党委书记党建工作汇报材料
2014/11/02 职场文书
2015-2016年小学教导工作总结
2015/07/21 职场文书
运动会班级口号霸气押韵
2015/12/24 职场文书
MySQL串行化隔离级别(间隙锁实现)
2022/06/16 MySQL