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之水平横向滚动歌词同步的应用
May 07 Javascript
js 剪切板的用法(clipboardData.setData)与js match函数介绍
Nov 19 Javascript
用jQuery模拟select下拉框的简单示例代码
Jan 26 Javascript
js实现的二级横向菜单条实例
Aug 22 Javascript
Node.js编写爬虫的基本思路及抓取百度图片的实例分享
Mar 12 Javascript
js实现百度搜索提示框
Feb 05 Javascript
js定时器实现倒计时效果
Nov 05 Javascript
jquery获取select选中值的文本,并赋值给另一个输入框的方法
Aug 21 jQuery
ES7之Async/await的使用详解
Mar 28 Javascript
vue实现新闻展示页的步骤详解
Apr 11 Javascript
微信小程序在线客服自动回复功能(基于node)
Jul 03 Javascript
微信小程序wxml列表渲染原理解析
Nov 27 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
Ajax+PHP边学边练 之五 图片处理
2009/12/03 PHP
php读取文件内容的几种方法详解
2013/06/26 PHP
php简单操作mysql数据库的类
2015/04/16 PHP
ThinkPHP中使用Ueditor富文本编辑器
2015/09/02 PHP
PHP给源代码加密的几种方法汇总(推荐)
2018/02/06 PHP
PHP创建对象的六种方式实例总结
2019/06/27 PHP
laravel框架中控制器的创建和使用方法分析
2019/11/23 PHP
doctype后如何获得body.clientHeight的方法
2007/07/11 Javascript
asp(javascript)全角半角转换代码 dbc2sbc
2009/08/06 Javascript
JavaScript 动态创建VML的方法
2009/10/14 Javascript
读JavaScript DOM编程艺术笔记
2011/11/15 Javascript
吐槽一下我所了解的Node.js
2014/10/08 Javascript
JQuery boxy插件在IE中边角图片不显示问题的解决
2015/05/20 Javascript
jquery实现右侧栏菜单选择操作
2016/03/04 Javascript
jQuery UI实现动画效果代码分享
2018/08/19 jQuery
浅析微信扫码登录原理(小结)
2018/10/29 Javascript
Vue使用富文本编辑器Vue-Quill-Editor(含图片自定义上传服务、清除复制粘贴样式等)
2020/05/15 Javascript
快速解决element的autofocus失效问题
2020/09/08 Javascript
Python解惑之整数比较详解
2017/04/24 Python
Python探索之URL Dispatcher实例详解
2017/10/28 Python
selenium+python实现1688网站验证码图片的截取功能
2018/08/14 Python
python pexpect ssh 远程登录服务器的方法
2019/02/14 Python
Django后台admin的使用详解
2019/07/08 Python
python实现比对美团接口返回数据和本地mongo数据是否一致示例
2019/08/09 Python
深入了解python中元类的相关知识
2019/08/29 Python
python接口自动化如何封装获取常量的类
2019/12/24 Python
python的launcher用法知识点总结
2020/08/07 Python
党委书记岗位职责
2013/11/24 职场文书
旅游管理专业个人求职信范文
2013/12/24 职场文书
后进生转化工作制度
2014/01/17 职场文书
女生节标语
2014/06/26 职场文书
中学生打架检讨书
2014/10/13 职场文书
党员反对四风思想汇报范文
2014/10/25 职场文书
公司2014年度工作总结
2014/12/10 职场文书
2014初中数学教研组工作总结
2014/12/19 职场文书
Redis入门基础常用操作命令整理
2022/06/01 Redis