因为是配套写的,如果是后端是用egg框架写的话,建议配合我写的另一篇文章观看,不是egg框架也建议去看看。
egg框架(通过egg-socket.io建立即时通讯服务,实现聊天功能)
1.安装插件
npm install socket.io-client
npm install vue-socket.io-extended
其实一开始我是用vue-socket.io的,毕竟教程多,但是我装完后在vue实例上死活找不到$socket
,也就不能通过this.$socket
来调用它的方法了,但是那些教程里都写安装完插件,main.js里引进来,vue.use一下就行了,我看了好多文档都不行,后来看到vue-socket.io-extended,发现才几kb,果断切换到该插件,装完console了一下this,挂载到vue上了,爽到。
但无论你用vue-socket.io还是vue-socket.io-extended,本质上都是对socket.io进行二次封装,这个socket.io-client可以说是必装吧,装了这个才能把socket挂载到vue上。并可以通过this.$socket
来调用socket的各种方法,如果是vue-socket.io-extended的话是通过this.$socket.client
来调用。
2.在main.js中引入
import VueSocketIOExt from 'vue-socket.io-extended';
import io from 'socket.io-client';
const socket = io('http://localhost:7001/');
Vue.use(VueSocketIOExt, socket);
emmm,上面这个是官方文档提供的引入方式,其实就相当于以下代码
import VueSocketIOExt from 'vue-socket.io-extended';
import socketio from 'socket.io-client';
Vue.use(VueSocketIOExt, socketio('http://localhost:7001/'));
3.在项目中使用
export default {
data() {
return {
msg:'',
msgList: [],
}
},
mounted(){
console.log(this)
},
sockets: {
connect: function () {
const id = this.$socket.client.id
console.log(id +' connected')
},
customEmit: function (data) {
console.log(data)
console.log('this method was fired by the socket server. eg: io.emit("customEmit", data)')
},
res: function (data) {
this.msgList.push(data)
console.log('接收到服务端消息', data);
}
},
methods: {
send(){
// 给服务器发送一个字符串:
console.log('send')
this.msgList.push({
name: 'U.amazing',
msg:this.msg
})
this.$socket.client.emit('server', {
name: 'U.amazing',
msg:this.msg
})
this.msg=''
}
}
}
this.$socket.client.emit()
就是向服务端发送数据的方法,第一个参数跟egg路由第一个参数一致,这里我第一个参数是’server’,
egg端路由如下,请求调用的的是io.controller.default中的index方法
io.of('/').route('server', io.controller.default.index);
4.该单文件模板代码如下:
如要引用测试,请注意我导入了两张本地图片,并且使用了css预处理器stylus,请自行处理。
<template>
<div class="home">
<div class="chat">
<div class="chat-container">
<ul class="chatList">
<li v-for="(item,index) in msgList" :key="index">
<div v-if="item.name == 'U.amazing'" class="me">
<div class="content">
<p>姓名:{{item.name}}</p>
<p>消息:{{item.msg}}</p>
</div>
<div class="img">
<img src="../assets/chat/user.jpg" alt="">
</div>
</div>
<div v-else class="other">
<div class="img">
<img src="../assets/chat/robot.jpg" alt="">
</div>
<div class="content">
<p>姓名:{{item.name}}</p>
<p>消息:{{item.msg}}</p>
</div>
</div>
</li>
</ul>
</div>
<div class="chat-input">
<el-input @keyup.enter.native="send()" type="textarea" :autosize="{ minRows: 4, maxRows: 6 }" maxlength="300" placeholder="请输入内容"
v-model="msg" />
</div>
</div>
</div>
</template>
<script>
export default {
data() {
return {
msg:'',
msgList: [],
}
},
mounted(){
console.log(this)
},
sockets: {
connect: function () { //建立连接后调用的函数
const id = this.$socket.client.id
console.log(id +' connected')
},
customEmit: function (data) {
console.log(data)
console.log('this method was fired by the socket server. eg: io.emit("customEmit", data)')
},
res: function (data) { //接受到消息后调用的函数
this.msgList.push(data)
console.log('接收到服务端消息', data);
}
},
methods: {
send(){
// 给服务器发送一个字符串:
this.msgList.push({
name: 'U.amazing',
msg:this.msg
})
this.$socket.client.emit('server', {
name: 'U.amazing',
msg:this.msg
})
this.msg=''
}
}
}
</script>
<style lang="stylus" scope>
.home {
.chat {
&-container {
padding 10px
border 1px solid rgba(0,0,0,0.1)
.chatList{
li{
padding 20px 0
}
.img{
width 50px
height 50px
border-radius 50%
overflow hidden
box-shadow 0 0 3px rgba(0,0,0,0.4)
img{
width 100%
height 100%
}
}
.me{
display flex
justify-content flex-end
.content{
margin-right 10px
padding 5px
border 1px solid #ccc
border-radius 5px
}
}
.other{
display flex
justify-content flex-start
.content{
margin-left 10px
padding 5px
border 1px solid #ccc
border-radius 5px
}
}
}
}
&-input{
padding 10px
border 1px solid rgba(0,0,0,0.1)
border-top none
}
}
}
</style>