Vue + WebSocket 项目小型聊天室

聊天室的实现核心在于 WebSocket 协议。通过为双方建立全双工通信,使得用户端可以随时接收来自服务端的数据。

WebSocket 如图:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-dTs6i6Pu-1657783935480)(vue-media/websocket与http.png)]

聊天信息渲染为数组

以数组的形式存储聊天数据,并在页面中使用 v-for 进行遍历循环:

<tempalte>
	<!-- 聊天区域 -->
    <div class="chat">
      <div class="item" v-for="(item, index) in chatList" :key="index">
        <van-image class="img" :class="{ right: item.isme }" round src="xx.xx"></van-image>
        <div class="con" :class="{ right: item.isme }"> {{ item.t }} </div>
      </div>
    </div>
</tempalte>

<script>
    export default {
        data() {
            return {
                // 输入框中的内容
                msg: "",
                // 聊天的数组
                chatList: [
                    { isme: false, t: "你好啊!" },
                    { isme: true, t: "你好!" },
                ],
            };
        },
    }
</script>

实时滚动到底部

每次发送信息之后,需要及时滚动到底部以展示发送的信息。

submit() {
    // 点击之后将输入框中的内容添加到 chatList 中
    if (this.msg) {
        this.chatList.push({
            isme: true,
            t: this.msg,
        });
        this.msg = "";
        this.$nextTick(() => {
            // 滚动到最后面
            this.$refs.chat.scrollTop = this.$refs.chat.scrollHeight;
        });
    }
},

使用 socket.io 库完成聊天功能

WebSocket 提供了 socket.io 的 JavaScript 库,它简化并兼容了 WebSocket 协议的编码实现。

  • 下载第三方包:
# 下载socket.io 客户端版本,我们的项目只用的上客户端(建议版本)
npm i socket.io-client
# 下载socket.io 全套(包括端服务端用的和客户端用的)(不建议)
npm i socket.io
  • 建立服务器的连接

    let socket = io('http://toutiao.itheima.net', {
        query: {
            token: 用户token
        },
        transports: ['websocket']
    })
    
  • 收消息

    socket.on('message', function (data) {})
    
  • 发消息

    socket.emit('message', {
        msg: '消息内容',
        timestamp: '发送消息的时间戳'
    })
    
实现
<template>
  <div class="zhi">
    <!-- 聊天区域 -->
    <div class="chat" ref="chatList">
      <div class="item" v-for="(item, index) in chatList" :key="index">
        <van-image class="img" :class="{ right: item.isme }" round src="xx.xx"></van-image>
        <div class="con" :class="{ right: item.isme }">
          {{ item.t }}
        </div>
      </div>
    </div>
    <!-- 输入框区域 -->
    <van-search class="input" v-model="msg" show-action left-icon="" placeholder="说点什么" @search="submit">
      <template #action>
        <div @click="submit">提交</div>
      </template>
    </van-search>
  </div>
</template>

<script>
  import io from 'socket.io-client';

  export default {
    name: 'Custom',
    data() {
      return {
        // 输入框中的内容
        msg: "",
        he: 'https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fpic.jj20.com%2Fup%2Fallimg%2Fmn02%2F022420152S4%2F200224152S4-5.jpg&refer=http%3A%2F%2Fpic.jj20.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1641711357&t=432633c617c691b75441a765c2729f61',
        me: 'https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fpic.jj20.com%2Fup%2Fallimg%2Fmn02%2F022420152S4%2F200224152S4-5.jpg&refer=http%3A%2F%2Fpic.jj20.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1641711357&t=432633c617c691b75441a765c2729f61',
        chatList: [
          // isme:当前对话是属于小智还是我(小智:false, 我:true)
          // t:聊天的内容
          { isme: false, t: '你好啊!' },
        ],
        socket: null
      };
    },
    methods: {
      // 1.0 点击右侧的提交按钮时会触发
      // 2.0 在输入框中点击回车按钮会触发
      submit() {
        // 点击之后将输入框中的内容添加到 chatList 中
        if (this.msg) {
          // 将消息发送到服务器
          this.socket.emit("message", {
            msg: this.msg,
            timestamp: Date.now(),
          });
          this.chatList.push({
            isme: true,
            t: this.msg,
          });
          this.msg = "";
          this.$nextTick(() => {
            // 滚动到最后面
            this.$refs.chatList.scrollTop = this.$refs.chatList.scrollHeight;
          });
        }
      },
    },
    created() {
      //建立连接
      this.socket = io('http://toutiao.itheima.net', {
        query: {
          token: 'dwjidwjio'
        },
        transports: ['websocket']
      });

      //监听服务器
      this.socket.on("message", (data) => {
        console.log(data);
        // 将内容添加到聊天列表中
        this.chatList.push({
          isme: false,
          t: data.msg,
        });
        // 自动滚动到底部
        this.$nextTick(() => {
          // 滚动到最后面
          this.$refs.chatList.scrollTop = this.$refs.chatList.scrollHeight;
        });
      });
    }
  };
</script>

<style lang="scss">
  .zhi {
    font-size: 16px;

    .chat {
      position: fixed;
      top: 46px;
      bottom: 54px;
      left: 0px;
      right: 0px;
      background-color: #eee;
      overflow: auto;

      .item {
        overflow: hidden;
        margin: 10px;

        .img {
          float: left;
          width: 40px;
          height: 40px;
          margin-right: 10px;

          &.right {
            float: right;
            margin-right: 0px;
            margin-left: 10px;
          }
        }

        .con {
          float: left;
          border: 1px solid #3196fa;
          max-width: 70%;
          padding: 10px;
          background-color: #e0effb;

          &.right {
            float: right;
            border: 1px solid #c5e2d4;
            background-color: #9eea6a;
          }
        }
      }
    }

    .input {
      position: fixed;
      bottom: 0px;
      left: 0px;
      width: 100%;
      padding: 10px;
    }
  }
</style>
  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值