Vue框架(使用vue-socket.io-extended实现聊天功能)

宇文灿
2023-12-01

因为是配套写的,如果是后端是用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>
 类似资料: