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 检测浏览器和操作系统的脚本
Dec 26 Javascript
JavaScript 获取当前时间戳的代码
Aug 05 Javascript
Js数组的操作push,pop,shift,unshift等方法详细介绍
Dec 28 Javascript
基于jquery实现控制经纬度显示地图与卫星
May 20 Javascript
JavaScript中的Web worker多线程API研究
Dec 06 Javascript
jquery简单实现带渐显效果的选项卡菜单代码
Sep 01 Javascript
angularjs学习笔记之双向数据绑定
Sep 26 Javascript
实例详解angularjs和ajax的结合使用
Oct 22 Javascript
基于JavaScript实现简单的随机抽奖小程序
Jan 05 Javascript
d3.js中冷门却实用的内置函数总结
Feb 04 Javascript
js实现的格式化数字和金额功能简单示例
Jul 30 Javascript
详解Vue中的MVVM原理和实现方法
Jul 15 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者的疑难问答(1)
2006/10/09 PHP
PHP7下协程的实现方法详解
2017/12/17 PHP
告诉大家什么是JSON
2008/06/10 Javascript
Javascript简单实现可拖动的div
2013/10/22 Javascript
js 金额格式化来回转换示例
2014/02/23 Javascript
js调试工具console.log()方法查看js代码的执行情况
2014/08/08 Javascript
javascript中if和switch,==和===详解
2015/07/30 Javascript
jQuery实现带有动画效果的回到顶部和底部代码
2015/11/04 Javascript
js实现简单的选项卡效果
2017/02/23 Javascript
js实现音频控制进度条功能
2017/04/01 Javascript
Bootstrap Table 删除和批量删除
2017/09/22 Javascript
Angular实现的简单定时器功能示例
2017/12/28 Javascript
nodejs中Express与Koa2对比分析
2018/02/06 NodeJs
element-ui使用导航栏跳转路由的用法详解
2018/08/22 Javascript
如何封装了一个vue移动端下拉加载下一页数据的组件
2019/01/06 Javascript
JavaScript使用表单元素验证表单的示例代码
2019/08/20 Javascript
[03:30]完美盛典趣味短片 CSGO2019年度名场面
2019/12/07 DOTA
python实现保存网页到本地示例
2014/03/16 Python
浅谈Python 列表字典赋值的陷阱
2019/01/20 Python
Python使用for生成列表实现过程解析
2020/09/22 Python
Nike瑞典官方网站:Nike.com (SE)
2018/11/26 全球购物
Janie and Jack美国官网:GAP旗下的高档童装品牌
2019/09/09 全球购物
泰国排名第一的家居用品中心:HomePro
2020/11/18 全球购物
人事部专员岗位职责
2014/03/04 职场文书
三八节主持词
2014/03/17 职场文书
学习交流会主持词
2014/04/01 职场文书
青春寄语大全
2014/04/09 职场文书
学校工作推荐信范文
2014/07/11 职场文书
合伙购房协议样本
2014/10/06 职场文书
招商引资工作汇报材料
2014/10/28 职场文书
2015年见习期工作总结
2014/12/12 职场文书
餐饮店长岗位职责
2015/04/14 职场文书
母亲节感言
2015/08/03 职场文书
送给小学生的暑假礼物!小学生必背99首古诗
2019/07/02 职场文书
GoLang中生成UUID唯一标识的实现
2021/05/08 Golang
Java 获取Word中所有的插入和删除修订的方法
2022/04/06 Java/Android