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 获取表单text,areatext,radio,checkbox,select值的代码
Nov 12 Javascript
jquery插件制作教程 txtHover
Aug 17 Javascript
form.submit()不能提交表单的原因分析
Oct 23 Javascript
jQuery操作DOM之获取表单控件的值
Jan 23 Javascript
javascript实现网页子页面遍历回调的方法(涉及 window.frames、递归函数、函数上下文)
Jul 27 Javascript
JS实现太极旋转思路分析
Dec 09 Javascript
老生常谈js-react组件生命周期
May 02 Javascript
详解ajax的data参数错误导致页面崩溃
Apr 30 Javascript
vue使用v-for实现hover点击效果
Sep 29 Javascript
JavaScript面向对象编程小游戏---贪吃蛇代码实例
May 15 Javascript
详解Vue.js 作用域、slot用法(单个slot、具名slot)
Oct 15 Javascript
微信小程序实现单个或多个倒计时功能
Nov 01 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通过正则表达式下载图片到本地的实现代码
2011/09/19 PHP
php截取html字符串及自动补全html标签的方法
2015/01/15 PHP
php中smarty模板条件判断用法实例
2015/06/11 PHP
java微信开发之上传下载多媒体文件
2016/06/24 PHP
PHP PDOStatement::fetch讲解
2019/01/31 PHP
js变量作用域及可访问性的探讨
2006/11/23 Javascript
让GoogleCode的SVN下的HTML文件在FireFox下正常显示.
2009/05/25 Javascript
25个非常棒的jQuery滑块插件和教程小结
2011/09/02 Javascript
iframe子页面获取父页面元素的方法
2013/11/05 Javascript
javascript得到当前页的来路即前一页地址的方法
2014/02/18 Javascript
nodejs中使用多线程编程的方法实例
2015/03/24 NodeJs
javascript中判断json的方法总结
2015/08/27 Javascript
js实现的奥运倒计时时钟效果代码
2015/12/09 Javascript
纯JS实现弹性导航条效果
2017/03/06 Javascript
python 连接各类主流数据库的实例代码
2018/01/30 Python
python 实现倒排索引的方法
2018/12/25 Python
对pandas写入读取h5文件的方法详解
2018/12/28 Python
python实现名片管理系统项目
2019/04/26 Python
python opencv实现图像边缘检测
2019/04/29 Python
Python3实现汉语转换为汉语拼音
2019/07/08 Python
线程安全及Python中的GIL原理分析
2019/10/29 Python
django实现用户注册实例讲解
2019/10/30 Python
Python彻底删除文件夹及其子文件方式
2019/12/23 Python
Python字符串格式化常用手段及注意事项
2020/06/17 Python
python爬虫搭配起Bilibili唧唧的流程分析
2020/12/01 Python
KIEHL’S科颜氏官方旗舰店:源自美国的顶级护肤品牌
2018/06/07 全球购物
出纳工作检讨书
2014/10/18 职场文书
2015年党员创先争优承诺书
2015/01/22 职场文书
教师辞职书范文
2015/02/26 职场文书
让生命充满爱观后感
2015/06/08 职场文书
祝寿主持词
2015/07/02 职场文书
读《瓦尔登湖》有感:每个人都需要一个瓦尔登湖
2019/10/17 职场文书
《烈火英雄》观后感:致敬和平时代的英雄
2019/11/11 职场文书
css实现文章分割线样式的多种方法总结
2021/04/21 HTML / CSS
react中props 的使用及进行限制的方法
2021/04/28 Javascript
MySQL 常见存储引擎的优劣
2021/06/02 MySQL