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 相关文章推荐
TextArea不支持maxlength的解决办法(jquery)
Sep 13 Javascript
日历查询的算法 如何计算某一天是星期几
Dec 12 Javascript
js对文章内容进行分页示例代码
Mar 05 Javascript
js函数内变量的作用域分析
Jan 12 Javascript
javascript排序函数实现数字排序
Jun 26 Javascript
浅析JavaScript访问对象属性和方法及区别
Nov 16 Javascript
React Native 环境搭建的教程
Aug 19 Javascript
通过js控制时间,一秒一秒自己动的实例
Oct 25 Javascript
使用bootstrap实现下拉框搜索功能的实例讲解
Aug 10 Javascript
关于JavaScript中高阶函数的魅力详解
Sep 07 Javascript
关于AOP在JS中的实现与应用详解
May 06 Javascript
vue路由权限校验功能的实现代码
Jun 07 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 输出双引号&quot;与单引号'的方法
2010/05/09 PHP
php数组(array)输出的三种形式详解
2013/06/05 PHP
php用户注册页面利用js进行表单验证具体实例
2013/10/17 PHP
php事件驱动化设计详解
2016/11/10 PHP
CSS常用网站布局实例
2008/04/03 Javascript
js select常用操作控制代码
2010/03/16 Javascript
jQuery LigerUI 使用教程表格篇(1)
2012/01/18 Javascript
10个基于浏览器的JavaScript调试工具分享
2013/02/07 Javascript
Javascript Throttle &amp; Debounce应用介绍
2013/03/19 Javascript
JavaScript设计模式之工厂方法模式介绍
2014/12/28 Javascript
jquery实现简单的二级导航下拉菜单效果
2015/09/07 Javascript
多种js图片预加载实现方式分享
2016/02/19 Javascript
EasyUI中在表单提交之前进行验证
2016/07/19 Javascript
webpack2.0搭建前端项目的教程详解
2017/04/05 Javascript
详解js几个绕不开的事件兼容写法
2017/08/30 Javascript
python中的yield使用方法
2014/02/11 Python
django实现分页的方法
2015/05/26 Python
Python环境下安装使用异步任务队列包Celery的基础教程
2016/05/07 Python
Tensorflow环境搭建的方法步骤
2018/02/07 Python
对numpy中向量式三目运算符详解
2018/10/31 Python
PyQt5实现从主窗口打开子窗口的方法
2019/06/19 Python
基于Python+Appium实现京东双十一自动领金币功能
2019/10/31 Python
wxPython实现分隔窗口
2019/11/19 Python
python获取响应某个字段值的3种实现方法
2020/04/30 Python
Python-openpyxl表格读取写入的案例详解
2020/11/02 Python
python中@property的作用和getter setter的解释
2020/12/22 Python
利用python绘制正态分布曲线
2021/01/04 Python
html5中的一些标签学习(心得)
2016/10/18 HTML / CSS
详解H5 活动页之移动端 REM 布局适配方法
2017/12/07 HTML / CSS
YesStyle美国/全球:购买亚洲时装、美容化妆品和生活百货
2017/01/16 全球购物
伦敦时尚生活的缩影:LN-CC
2017/01/24 全球购物
校园之星获奖感言
2014/01/29 职场文书
县人大领导班子四风对照检查材料思想汇报
2014/10/09 职场文书
学校施工安全责任书
2015/01/29 职场文书
2015应届毕业生自荐信范文
2015/03/05 职场文书
八年级作文之我的母亲
2019/12/10 职场文书