基于vue2.x实现的即时通讯程序仿微信聊天6对接好友列表以及记录接口和socketIo讲授

  • 这节课来对接通讯录好友列表接口好友聊天记录接口·
  • 对接通讯录好友列表接口

  • 打开接口文档https://www.showdoc.com.cn/2035654172307363/9197156730533694
  • 1、打开项目,复制对应的接口路径到项目的src/api/index.js
const api = {
  GetMyFriends:'/api/myfriends'
}
  • 2、在src/api/user.js中新建api接口方法
// 获取我的好友列表
export function getMyFriends(data) {
  return request({
    url: api.GetMyFriends,
    method: 'post',
    data,
  })
}
  • 3、复制你新建的api方法名到需要引入到页面,也就是【通讯录页面】,通过import导入
import { getMyFriends } from '@/api/user'
  • 4、然后在methods方法函数内,新建获取好友列表的自定义方法,在该方法内调用getMyFriends接口方法
methods:{
   async getMyFriendsFun() {
      try {
        const res = await getMyFriends()
        console.log(res)
        this.list = res.data //注意:【list】要在data内预定义成空数组,即 list:[]
      } catch (error) {
        console.log(error)
      }
    }
}
  • 注意:【list】要在data内预定义成空数组,即 list:[ ]

  • 5、然后在mounted生命周期函数内调用getMyFriendsFun方法
  mounted () {
    this.getMyFriendsFun();
  }
  • 然后就获取到数据了~
image.png
  • 6、最后for循环这个list数组,进行数据绑定就搞定了这个通讯录好友列表了
image.png

  • 对接好友聊天记录接口

  • 1、打开接口文档https://www.showdoc.com.cn/2035654172307363/9197322103805778
  • 2、复制对接的接口地址路径到src/api/index.js文件中粘贴
const api = {
  GetChatMsg:'/api/query/msg'
}
  • 3、打开src/api/user.js文件,新建api接口方法,注意看清楚接口的请求方式,根据接口文档来看
// 获取好友列表记录
export function getChatMsg(params) {
  return request({
    url: api.GetChatMsg,
    method: 'get',
    params,
  })
}
  • 4、然后复制接口方法名到需要引入的页面,即chatDetail页面
import { getChatMsg } from '@/api/user';
  • 5、因为这个聊天详情页面是动态路由匹配的,所以我们在上个页面跳转的时候,要传入真实的id参数
  • 6、打开通讯录页面,找到跳转方法toDetailPage,修改传入的id参数
methods:{
  toDetailPage(item) {
      this.$router.push('/chatDetail/'+item._id)
  },
}
  • 7、然后在methods方法函数内新建获取好友聊天记录的自定义方法
methods:{
  async getChatMsgFun() {
      try {
        const res = await getChatMsg({ toId: this.$route.params.id })
        console.log(res);
        this.list = res.data; //注意:【list】要在data内预定义成空数组,即 list:[]
      } catch (error) {
        console.log(err)
      }
    }
}
  • 注意:【list】要在data内预定义成空数组,即 list:[]

  • 8、然后在mounted生命周期内调用getChatMsgFun方法
mounted () {
    this.getChatMsgFun();
},
  • 然后就获取到数据了~
image.png
  • 9、下面就是要渲染该数据了,但是因为我们中间的区域是引入的外部组件,所以要先把得到的list数组数据,通过父子组件传值的形式,传递过去,子组件使用props来接收传递过去的数组
  • 在子组件身上v-bind动态绑定传值
image.png
  • 子组件内部使用props接收传递过来的list
image.png
  • 子组件data中的list没用了,就可以删除掉了!!!

image.png
  • 10、下面就是要处理下渲染出来的数据,根据实际情况渲染,目前是这个样子的
image.png
  • 先渲染右侧数据,【我是你师傅】和【悟空好绕啊】这两条消息我们现在登陆的这个唐僧的账号发出的,所以,根据接口返回数据和接口返回字段对比
image.png

image.png
  • 如果将我们当前登录账户人发送的消息渲染在右侧呢?
  • 其他send_id是发送者的id,那谁是发送者呢?当然是当前登录的账户人是发送者,那么将此send_id当前登录账户人的个人id进行对比,如果相等就是渲染在右侧的!
  • send_id有了,现在的问题是如何获取到当前登录账户人的id呢?
  • 这就需要修改下获取个人信息接口存储的数据
  • 打开src/store/modules/app.js
image.png
getUserInfo({ commit, state }) {
    return new Promise((resolve, reject) => {
      getUserInfo().then(response => {
        const { data } = response
        if (!data) {
          return reject('Verification failed, please Login again.')
        }
        const { username } = data
        commit('SET_USER_NAME', data)
        resolve(data)
      }).catch(error => {
        reject(error)
      })
    })
  },
  • 这样,我们vuex中state里的userName存储的就是当前登录账户人的个人信息了,就是下图,id就在里面

image.png
  • 11、我们可以通过vuex的mapGetters来拿到上图中的对象数据
  • 先在chatDetail页面引入mapGetters
import { mapGetters } from 'vuex';
  • 在通过计算属性拿到userName对象
computed: {
    ...mapGetters(['userName'])
},
  • 12、下面就可以渲染右侧的聊天记录数据了
image.png
  • 那么右侧的数据就渲染好了,在渲染下头像send_avatar就搞定右侧了
image.png
13、下面来分析下如何渲染左侧数据
  • 首先 我们的地址栏参数,那个id就是对方的id,也就是和谁聊天的那个人的id,那么针对左侧的聊天记录来说,左侧的消息是谁发的呢?是对方发的,那么对方就是发送方,那左侧聊天信息的send_id就是发送方的id,那么既然地址栏参数,那个id就是对方的id,那地址栏的id==左侧聊天信息的send_id是不是就可以渲染左侧数据了呢
image.png
  • 搞定!!!






image.png
  • 还有一步就是,顶部的对方的名字 需要渲染出来,无非就是在上一级页面跳转的时候多传一个参数,然后这个页面接收渲染一下即可,同学们自己来试试呢??


  • 浅谈socketIO双向通信数据交换技术

  • 何为socketIO?

  • Socket.IO是一个库,基于 Node.js 的实时应用程序框架。可以在浏览器和服务器之间实现实时,双向和基于事件的通信。它适用于每个平台、浏览器或设备,同样注重可靠性和速度。
  • 起源:

  • WebSocket 的产生源于 Web 开发中日益增长的实时通信需求,对比基于 http 的轮询方式,它大大节省了网络带宽,同时也降低了服务器的性能消耗。
  • WebSocket 协议在2008年诞生,2011年成为国际标准。虽然主流浏览器都已经支持,但仍然可能有不兼容的情况,为了兼容所有浏览器,就诞生SocketIO。
  • SocketIO将WebSocket、AJAX和其它的通信方式全部封装成了统一的通信接口,也就是说,我们在使用SocketIO时,不用担心兼容问题,底层会自动选用最佳的通信方式。
  • Socket.io有什么特点?

  • 易用性:Socket.io封装了服务端和客户端,使用起来非常简单方便。
  • 跨平台:Socket.io是跨平台的,可以实现多平台的即时通讯,Socket.io支持跨平台,这就意味着你有了更多的选择,可以在自己喜欢的平台下开发实时应用。由于 iOS 端进行 socket 编程主要使用 GCDAsyncSocket 框架,但要实现 Android、iOS、web 多平台的通讯,还是选择统一的框架或协议比较好。
  • 自适应:Socket.io 实现了实时双向的基于事件的通讯机制,是基于 webSocket 的封装,但它不仅仅包括 webSocket,还对轮询(Polling)机制以及其它的实时通信方式封装成了通用的接口,并且在服务端实现了这些实时机制的相应代码,它会自动根据浏览器从WebSocket、AJAX长轮询、Iframe流等等各种方式中选择最佳的方式来实现网络实时应用,非常方便和人性化,而且支持的浏览器最低达IE5.5。
  • Socket.io 常用内置事件、方法

  • connect 连接socket服务方法(客户端可使用)
  • connection 监听客户端连接的事件(服务端使用on监听使用)
  • disconnect 监听客户端断开链接的事件 (服务端使用on监听使用)
  • emit 注册自定义事件方法(客户端、服务端均可使用)
  • on 监听自定义事件方法(客户端、服务端均可使用)

  • Scoket.io的实际应用

  • (注意:前后端都需要使用Socket.io才能通信)
  • 服务端,基于node.js搭建服务端,需要安装socket.io插件

cnpm install socket.io --save

---- 代码演示过程

var express = require('express');
var router = express.Router();
/**
 * socket.io
 */
var app = express();
var server = require('http').Server(app);
var io = require('socket.io')(server, {
  transports: ['websocket']
});
server.listen(3001);
/**
 * 监听客户端连接
 */
io.on('connection', function (socket) {
  console.log("客户端连接成功~");
});


module.exports = router;

  • app.js引入这个文件,如果引入过了 就不需要再重复引入了
require("./routes/index")
  • 后端socket服务搭建完成,socket服务地址是: ws://localhost:3001

  • 客户端,基于vue.js搭建客户端,需要安装socket.io-client插件和vue-socket.io-extended插件

cnpm  install socket.io-client vue-socket.io-extended --save
  • main.js内引入自定义js文件socketIo.js
// 引入socket
import './utils/socketIo'
  • socketIo.js

import Vue from 'vue'
import VueSocketIOExt from 'vue-socket.io-extended';
import io from 'socket.io-client';
// 链接websocket
const socket = io.connect('ws://localhost:3001', {
    transports: ['websocket'],
})
Vue.use(VueSocketIOExt, socket);
image.png

image.png
  • 上图就是前后端建立了一个socket通讯服务
  • 下面演示如果进行事件的注册,事件的监听

  • 比如在前端链接上socket服务后,就立马推送一条消息给服务端,然后,服务端推送给所有客户端,说【xxx上线了,并说:xxxxx】

比如在chatDetail页面mounted生命周期内直接执行事件注册方法

mounted () {
      this.$socket.client.emit('sayHello', {
      name: this.$route.query.name == '孙悟空' ? '唐僧' : '孙悟空',
      message: this.$route.query.name == '孙悟空' ? '为师想留在女儿国~' : '俺老孙来也~'
    })
  },
image.png
  • 服务端需要监听一下这个sayHello事件,并广播给除自己外的所有人

/**
 * 监听客户端连接
 */
io.on('connection', function (socket) {
  console.log("客户端连接成功~");
  //广播给除发送者外的所有人
  socket.on("sayHello",data=>{
    socket.broadcast.emit("broMsg",data)
  })
});
image.png
  • vue前端监听服务端推送的信息
sockets:{
    broMsg: function (data) {
      this.info = data
    }
},
  • 然后简单处理下前端页面
 
{{info.name}}上线了,并说了一句{{info.message}}
  • 最终效果

image.png
  • 这还是只是广播形式的双向通信,如果要实现一对一的的实时通讯,服务端在推送的时候就要使用

  • to(toId)这个方法了,toId就是对方的唯一标识,只有这样才能推给对方,广播是推给除了自己外的所有人

  • 下面来实现一对一通讯

  • 1、就在chatDetail页面,点击发送按钮 ,发送消息
image.png
methods:{
   sendMsg() {
      if (this.value.trim() == '') {
        this.$toast('请输入聊天内容')
        return
      }
      let obj = {
        come_id: this.$route.params.id, //接收方的id
        send_id: this.userName._id, //发送方的id
        type: 1, //消息类型 1 文字消息
        send_avatar: this.userName.avatar, //发送者的头像
        message: this.value, //发送的文字内容
        send_name: this.userName.nickname, //发送者的昵称
        date:new Date(),//发送的当前时间
      }
      this.$socket.client.emit('sayOne', obj)
    }
}
  • 前端部分暂时告一段落,下面是【服务端】监听sayOne事件

image.png
  • 服务端监听到前端发来的数据,利用to(toId)方法发送给对方
  • 在开发服务端前,前端还是要注册触发一个login事件,传给后端来做【socket用户组】
  • 在刚进入这个页面的时候,也就是在mounted生命周期内,注册触发login事件
this.$socket.client.emit('login', this.userName._id)
  • 服务端来监听login事件,作用域外部定义一个空对象hashName,用来存储【socket用户组】
socket.on("login", data => {
    // console.log(data);
    var _id = data;
    hashName[_id] = socket.id;
})
  • 服务端监听sayOne事件
 /** 监听sayOne事件 */
  socket.on('sayOne', data => {
    // console.log(data);
    var toName = data.come_id;
    // console.log(hashName);
    // console.log(hashName[toName]);
    if (hashName[toName]) {
      socket.to(hashName[toName]).emit('message', data)
    }
  })
  • 下面回到前端,在sockets方法函数里,监听服务端注册message事件,得到服务端推过来的消息
 sockets: {
    message:function(data){
      // console.log(data);
      this.$refs.childCom.list.push(data)
    },
  },
  • 如下图
image.png
  • 最后一步,在push下list数组,渲染右侧数据

image.png
sendMsg() {
      if (this.value.trim() == '') {
        this.$toast('请输入聊天内容')
        return
      }
      let obj = {
        come_id: this.$route.params.id, //接收方的id
        send_id: this.userName._id, //发送方的id
        type: 1, //消息类型 1 文字消息
        send_avatar: this.userName.avatar, //发送者的头像
        message: this.value, //发送的文字内容
        send_name: this.userName.nickname, //发送者的昵称
        date:new Date(),//发送的当前时间
      }
      this.$socket.client.emit('sayOne', obj)
      this.$refs.childCom.list.push(obj)

    }
  • 如下图,已经实现了一对一通讯
image.png
  • 在最后一步,格式化下时间即可
image.png
{{$formatDate(item.date,'yyyy-MM-dd hh:mm:ss')}}
image.png

你可能感兴趣的:(基于vue2.x实现的即时通讯程序仿微信聊天6对接好友列表以及记录接口和socketIo讲授)