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 相关文章推荐
Juqery Html(),append()等方法的Bug解决方法
Dec 13 Javascript
js不能跳转到上一页面的问题解决方法
Mar 01 Javascript
jquery中获得元素尺寸和坐标的方法整理
May 18 Javascript
jQuery EasyUI菜单与按钮详解
Jul 13 Javascript
JavaScript中立即执行函数实例详解
Nov 04 Javascript
angular动态表单制作
Feb 23 Javascript
JavaScript 点击触发复制功能实例详解
Nov 02 Javascript
js使用Promise实现简单的Ajax缓存
Nov 14 Javascript
利用angular自动编译andriod APK的绕坑经历分享
Mar 08 Javascript
小程序实现长按保存图片的方法
Dec 31 Javascript
微信小程序实现组件顶端固定或底端固定效果(不随滚动而滚动)
Apr 09 Javascript
vue3 自定义图片放大器效果的示例代码
Jul 23 Vue.js
微信小程序从注册账号到上架(图文详解)
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
UCenter 批量添加用户的php代码
2012/07/17 PHP
基于linnux+phantomjs实现生成图片格式的网页快照
2015/04/15 PHP
php+ajax实现无刷新文件上传功能(ajaxuploadfile)
2018/02/11 PHP
PHP+MariaDB数据库操作基本技巧备忘总结
2018/05/21 PHP
php实现微信公众号创建自定义菜单功能的实例代码
2019/06/11 PHP
php 下 html5 XHR2 + FormData + File API 上传文件操作实例分析
2020/02/28 PHP
Js,alert出现乱码问题的解决方法
2013/06/19 Javascript
js图片处理示例代码
2014/05/12 Javascript
jQuery制作仿Mac Lion OS滚动条效果
2015/02/10 Javascript
Angular限制input框输入金额(是小数的话只保留两位小数点)
2017/07/13 Javascript
解决低版本的浏览器不支持es6的import问题
2018/03/09 Javascript
jQuery实现的手动拖动控制进度条效果示例【测试可用】
2018/04/18 jQuery
Vue.js watch监视属性知识点总结
2019/11/11 Javascript
[02:29]完美世界高校联赛上海赛区回顾
2015/12/15 DOTA
[02:02:38]VG vs Mineski Supermajor 败者组 BO3 第一场 6.6
2018/06/07 DOTA
初步介绍Python中的pydoc模块和distutils模块
2015/04/13 Python
python3写爬取B站视频弹幕功能
2017/12/22 Python
python opencv 图像尺寸变换方法
2018/04/02 Python
Python 实现将数组/矩阵转换成Image类
2020/01/09 Python
学会python自动收发邮件 代替你问候女友
2020/05/20 Python
FOREO官方网站:LUNA露娜洁面仪
2016/11/28 全球购物
Giglio美国站:意大利奢侈品购物网
2018/02/10 全球购物
荷兰网上药店:Drogisterij.net
2019/09/03 全球购物
西安启天科技有限公司网络工程师面试题笔试题
2016/06/12 面试题
写一个函数,要求输入一个字符串和一个字符长度,对该字符串进行分隔
2015/07/30 面试题
初中生学习的自我评价
2013/11/14 职场文书
会计电算化专业毕业生求职信范文
2013/12/10 职场文书
职业生涯规划怎么写
2013/12/29 职场文书
贷款担保申请书
2014/05/20 职场文书
卫生标语大全
2014/06/21 职场文书
纪律教育月活动总结
2014/08/26 职场文书
党员查摆四风问题思想汇报
2014/10/25 职场文书
红色故事汇观后感
2015/06/18 职场文书
办公室主任岗位竞聘书
2015/09/15 职场文书
JavaScript 中for/of,for/in 的详细介绍
2021/11/17 Javascript
windows server2008 开启端口的实现方法
2022/06/25 Servers