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 相关文章推荐
Javascript Select操作大集合
May 26 Javascript
javascript window.opener的用法分析
Apr 07 Javascript
理解Javascript_02_理解undefined和null
Oct 11 Javascript
重构Javascript代码示例(重构前后对比)
Jan 23 Javascript
jquery得到font-size属性值实现代码
Sep 30 Javascript
JavaScript中使用arguments获得函数传参个数实例
Aug 27 Javascript
jquery图片滚动放大代码分享(1)
Aug 25 Javascript
AngularJS压缩JS技巧分析
Nov 08 Javascript
JavaScript事件对象深入详解
Dec 30 Javascript
详解50行代码,Node爬虫练手项目
Apr 22 Javascript
javascript将扁平的数据转为树形结构的高效率算法
Feb 27 Javascript
JavaScript面向对象核心知识与概念归纳整理
May 09 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
德劲1104的电路分析与改良
2021/03/01 无线电
php通过COM类调用组件的实现代码
2012/01/11 PHP
使用php计算排列组合的方法
2013/11/13 PHP
用PHP去掉文件头的Unicode签名(BOM)方法
2017/06/22 PHP
PHP用PDO如何封装简单易用的DB类详解
2017/07/30 PHP
tp5框架前台无限极导航菜单类实现方法分析
2020/03/29 PHP
IE8 兼容性问题(属性名区分大小写)
2009/06/04 Javascript
readonly和disabled属性的区别
2015/07/26 Javascript
Javascript实现的简单右键菜单类
2015/09/23 Javascript
Bootstrap每天必学之表单
2015/11/23 Javascript
Knockout自定义绑定创建方法
2015/12/26 Javascript
基于javascript实现根据身份证号码识别性别和年龄
2016/01/22 Javascript
微信小程序 基础知识css样式media标签
2017/02/15 Javascript
基于Bootstrap的网页设计实例
2017/03/01 Javascript
深入理解Angularjs 脏值检测
2018/10/12 Javascript
微信小程序上传图片并等比列压缩到指定大小的实例代码
2019/10/24 Javascript
[02:20]DOTA2中文配音宣传片
2013/05/22 DOTA
[05:04]DOTA2上海特级锦标赛主赛事第二日TOP10
2016/03/04 DOTA
Python实现App自动签到领取积分功能
2018/09/29 Python
用Python将结果保存为xlsx的方法
2019/01/28 Python
Python 字符串、列表、元组的截取与切片操作示例
2019/09/17 Python
python读取csv文件指定行的2种方法详解
2020/02/13 Python
Python结合百度语音识别实现实时翻译软件的实现
2021/01/18 Python
基于HTML5 audio元素播放声音jQuery小插件
2011/05/11 HTML / CSS
原装进口全世界:天猫国际
2016/08/03 全球购物
有趣的睡衣和礼物:LazyOne
2019/11/27 全球购物
C#和SQL Server的面试题
2016/08/12 面试题
机电工程学生自荐信范文
2013/12/07 职场文书
机关财务管理制度
2014/01/17 职场文书
综合实践活动总结
2014/05/05 职场文书
教师求职信
2014/06/17 职场文书
告知书格式
2015/07/01 职场文书
婚宴父母致辞
2015/07/27 职场文书
HDFS免重启挂载新磁盘
2022/04/06 Servers
字节飞书面试promise.all实现示例
2022/06/16 Javascript
Mybatis 一级缓存和二级缓存原理区别
2022/09/23 Java/Android