Vue 使用 Vue

您所在的位置:网站首页 死人发来的信息完整版 Vue 使用 Vue

Vue 使用 Vue

2024-07-13 02:28| 来源: 网络整理| 查看: 265

技术讨论群【522121825】

1. 上次的博客已经讲述了如何建立服务器,如何建立客户端,并且与服务器进行连接,那么本文接着上次,讲述一下客户端与服务器端的通讯是如何实现的。

PS:事件的发布与监听、广播事件、私聊事件、其他常用事件。

 2. 事件的发布与监听:

        2.1 emit()、on():

        在vue中,组件可以发布自定义事件,使用emit,其他地方直接使用  on 监听这个事件即可。而socket.io 也是类似的,发布事件用 emit ,监听事件用 on;

// 监听客户端连接 io.on("connection", function (socket) { /* 每一个连接上来的用户,都会分配一个socket */ console.log("客户端有连接"); /* 监听登录事件 */ socket.on('login', data => { console.log('login', data); }); // 给客户端发送消息(发布welcome事件) socket.emit("welcome", "欢迎连接socket"); /* socket实例对象会监听一个特殊函数,关闭连接的函数disconnect */ socket.on('disconnect', function () { console.log('用户关闭连接'); }); });

         例如上的代码,服务器端监听了‘connection’事件,(connection事件是socket的默认事件,指的是用户连接),还监听了login事件,发布了一个 welcome事件,监听一个disconnection事件,(disconnection也是默认事件,指的是用户断开连接)

        2.2 发布与监听:

        发布事件,就是我想给你发消息。监听事件,就是我想收到你的消息。就是一个  ‘发-收’ 的关系。(我自己的理解哈)

3. 客户端监听与发布:

/* socket是监听服务器发布的自定义事件 */ sockets: { /* 监听welcome事件 */ welcome:function(data){ console.log("welcome data 数据返回 = >", data); }, },

这个是监听服务器发布的事件,用sockets监听;

methods: { /* 登录 */ login(){ console.log("login",this.username); /* 发送数据到服务器 */ this.$socket.emit('login',this.username); this.isLogin=true; this.msgList.push({type:'',msg:this.username+'登录成功'}); }, }

这个是发布事件,定义在methods中,使用 this.$socket.emit();

 4. 启动服务器与Vue:

连接了两个客户端, 服务器输出连接消息;

5. 群聊事件

        到此,已经简单讲述了事件的发布于监听,而socket.io的通讯就是建立在这个基础上。

我们使用vue-socket.io做聊天应用,无非就是私聊和群聊,下面慢慢来探究里面的技术;

        5.1 普通群聊:

socket.io 在群聊的处理上,是非常棒的!Introduction | Socket.IO  这个是socket.io 的官方文档,里面有更详细的描述。

我们还是先看一下服务器端的代码:

var io = require("socket.io")(http, { allowEIO3: true, cors: { origin: "http://localhost:8080", methods: ["GET", "POST"], credentials: true } }); // 监听客户端连接 io.on("connection", function (socket) { /* 每一个连接上来的用户,都会分配一个socket */ console.log("客户端有连接"); /* 监听登录事件 */ socket.on('login', data => { console.log('login', data); }); // 给客户端发送消息(发布welcome事件) socket.emit("welcome", "欢迎连接socket"); /* socket实例对象会监听一个特殊函数,关闭连接的函数disconnect */ socket.on('disconnect', function () { console.log('用户关闭连接'); }); });

我先解释一下,这里面有两个非常重要的变量:io、socket;

io是socket服务器对象(servers);

socket是每一个连接上来的客户端实例;

所以群聊,就是给连接上来的所有人发送消息!而所有人存在io 服务器对象中,因此,广播事件:

io.emit("hello", "world");

         5.2 socket.io 官方文档中,还有一点需要我们去注意的。

Rooms:A room is an arbitrary channel that sockets can join and leave. It can be used to broadcast events to a subset of clients: 

 我们可以加入房间或者离开房间,在广播事件的时候,就可以直接广播给该房间的客户端。

5.1我们说的是给连接上来的所有人,而现在这个是指定房间的客户端,还是有很大的区别的。

那么,我们如何定义房间,并给指定房间的客户端发送消息呢?

// 在客户端连接的时候,指定加入某一个房间 io.on("connection", (socket) => { socket.join("some room"); }); // 给指定房间的客户端连接发送消息 io.to("some room").emit("some event");

下面是房间的相关事件:

有兴趣的可以试试 

以上便是群聊的相关方法。 

          5.2 私聊:

官方文档并没有过多的描述私聊的实现,只是给了一段示例代码:

// to individual socketid (private message) io.to(socketId).emit(/* ... */);

对于这个私聊,下面我说说我的理解。

6. socket.io 私聊实现方案:

        6.1 新建数组实现

上述中的代码,我们只要找到你想私聊的客户端的socketid,调用这个API即可。但是连接上来的这么多客户端,我们是如何得知你想发送的对象的sockeid呢?

我们修改服务器端的代码如下:

// 定义数组接收数据 var socketInfo=[]; /* 监听登录事件 */ socket.on('login', data => { console.log('login', data); /* 将用户的id与socketid对应 */ socketInfo.push({ userid:data, socketid:socket.id }); console.log(socketInfo); });

客户端:

 服务器端:

这样一来,你想给谁发消息,只要在数组中遍历userid,取到这个socketid,即可实现。具体代码如下:(现在我是固定的  2 号,具体根据实际项目调整)

 客户端:

/* 发送消息 */ send() { /* 给服务器发送消息,就是发布一个事件,服务器监听即可! */ this.$socket.emit("1-2", { userid:'2', msg:this.msg, }); this.msg='' },

不难理解,需要带一个用户id,来唯一识别你想给谁发消息。同时,还要监听服务器发送过来的数据:

/* socket是监听服务器发布的自定义事件 */ sockets: { /* 监听私聊事件 */ chatPrivate:function(data){ console.log('有人找我私聊了',data); }, /* 监听welcome事件 */ welcome:function(data){ console.log("welcome data 数据返回 = >", data); }, },

 服务器端:

/* 这里我们模拟 1 给 2 发消息 */ socket.on('1-2',data=>{ /* 遍历数组 */ socketInfo.forEach(s=>{ /* 判断该对象是不是我们需要发送的那个人 */ if(s.userid==data.userid){ /* 发送数据 */ io.to(s.socketid).emit('chatPrivate',data.msg); } }); });

实现效果:

1号发送数据:

 2号接收数据:

以上便是基于数组实现私聊,总结一下,就是要对应连接上来的用户ID,和连接的socketid,当我发起私聊的时候,能够找到对应用户的socketid即可!根本就是找到对方的socketid!

        6.2 基于io服务器实例实现

io是socket服务器对象(servers);

socket是每一个连接上来的客户端实例;

这次我们不用建立数组,用原始的方式实现。socket是连接实例,肯定是一个对象,因为我们取id,是通过socket.id实现的。所以我们可以在对象上追加一个属性:userid;

那么,大概会变成这样子:

原来的socket:

socket:{

...

id:XXXXXXXXX

...

}

加了自定义属性后:

socket:{

...

id:XXXXXXXXX

userid:XXXXXX

...

}

这样,我们不就可以直接遍历存放socket的容器,找到userid,再取socketid不就实现了嘛??换句话说,连接上来的socket,应该是放在一个默认的数组中。这个默认的数组是什么?io?

socket添加自定义属性:

/* 监听登录事件 */ socket.on('login', data => { console.log('login', data); /* 添加自定义属性 */ socket.userid=data; });

下面是输出的io

 感兴趣的小伙伴可以慢慢研究。 

Server { _events: [Object: null prototype] {}, _eventsCount: 0, _maxListeners: undefined, ..... //此处省略 encoder: Encoder {}, _adapter: [class Adapter extends EventEmitter], sockets: Namespace { _events: [Object: null prototype] { connection: [Function (anonymous)] }, _eventsCount: 1, _maxListeners: undefined, sockets: Map(2) { 'R_pZZihjSjxrh8VaAAAA' => [Socket], 's2KCyEX2y0tBgDXhAAAC' => [Socket] }, _fns: [], _ids: 0, server: [Circular *1], name: '/', adapter: Adapter { _events: [Object: null prototype] {}, _eventsCount: 0, _maxListeners: undefined, nsp: [Circular *2], rooms: [Map], sids: [Map], encoder: Encoder {}, [Symbol(kCapture)]: false }, [Symbol(kCapture)]: false }, ........ //此处省略 }

相信有感觉的已经找到了socket!没错,就是io.sockets.sockets。(一定要注意:io.sockets.sockets 是存放所有连接的用户实例的数组!!数组!!(Map(2)))

我简单说一下为什么是io.sockets.sockets:

理论上,应该是io.sockets就行了,第一个很好理解,io指的是Server,第二个sockets指的是命名空间,因为同一个服务器,可以根据不同的namespace分配不同的用户连接。这个请详细看官网说明,这里不再深入研究。

涉及了一个命名空间,所以才是io.sockets.sockets

那么,有了这个数据,我们就遍历这个,找到对应userid和socketid,不就能实现了嘛?

/* 定义变量接收这个数组:一般我简写 scs */ var SocketConnections=io.sockets.sockets; console.log("客户端有连接"); /* 监听登录事件 */ socket.on('login', data => { console.log('login', data); /* 添加自定义属性 */ socket.userid=data; }); /* 这里我们模拟 1 给 2 发消息 */ socket.on('1-2',data=>{ /* 遍历数组 */ SocketConnections.forEach(s=>{ /* 判断该对象是不是我们需要发送的那个人 */ if(s.userid==data.userid){ /* 发送数据 */ io.to(s.id).emit('chatPrivate',data.msg); } }); });

注意:这里循环找的是id,不是socketid,socketid是我们自己定义的数组写的变量,而我们通过io.sockets.sockets找到的是socket本身,id就是他的属性!!! 

以上就是 io 原生方式找到对应的连接实例。

7. 总结:

        7.1 emit 发布事件

        7.2 on 监听事件

        7.3 io.emit() 群聊 [ 所有连接服务器的实例都会接收到消息 ]

        7.4 Rooms:io.to('room name').emit() [ 在某房间里的用户能接收到数据 ]

        7.5 私聊实现1:自定义数据,存放连接的唯一标识和socketid

        7.6 私聊实现2:io.sockets.sockets,默认的服务器实例对象数组

        7.7 私聊代码:io.to().emit()

        7.8 socket.io事件速查表

以上是我的理解,可能有些错误或者不准确,欢迎留言指正。

想要源码,欢迎留言 ,后续会更新基于vuex管理的socket.io的使用。



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3