Vue 使用 Vue-socket.io 实现即时聊天应用(实战篇 一)

目录 

1. 项目说明:

2. 项目的创建:

3. 使用编辑器打开项目:

4. 下载ElementUI:

5. 使用elementUI搭建聊天应用主体框架:

6. Footer的实现:

7. Aside的实现

7.1 渲染用户列表;

 7.2 个人信息:

 7.3 搜索框实现

8. vuex的设计:

9. Header实现:

10.Main的实现:

11. 总结:


1. 项目说明:

        技术讨论群【522121825】

        本项目基于vue2与cli3,使用vue-socket.io实现即时聊天的小应用,从项目的搭建,到服务器的创建、连接、通信;涵盖了我前三篇文章的内容,如遇到不理解的,还请回看之前的文章。

        项目主要分为上、下两篇,上篇讲述项目框架的搭建,包括聊天页面的搭建过程等;下篇主要是讲述基于vu-socekt.io实现聊天的业务处理,大家按需查看。

        该项目还是基于vue的,所以对vue基础知识的要求还是有的,有不理解的可以留言讨论哦,当然,这也是我个人打代码,难免出错,欢迎指正~

        好了,直接开始吧。求个赞呀~

2. 项目的创建:

进入cmd, 输入命令:vue ui ,使用可视化创建vue2的项目。

 

 

按照步骤,创建即可。(请选择vue2的项目)

3. 使用编辑器打开项目:

(我用的是VScode)打开项目之后,将默认的组件删除,并清空App组件的内容;(保证是一个空的项目)

4. 下载ElementUI:

使用elementui是为了更快的搭建项目框架,不用自己手敲那么多代码,还不好看。可以使用其他的框架,比如bootstrap等;

下载elementUI:

npm i element-ui --s

引用elementUI:

在main.js中引用:

import ElementUI from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css';

Vue.use(ElementUI);

5. 使用elementUI搭建聊天应用主体框架:

直接使用 container布局容器快速搭建聊天应用页面:(css也需要复制过来哦,放在App中

 到此,我们就能知道我们需要什么组件了:Aside、Header、Footer、Main(因为和HTML重名,所以加myxxx区分)

 思考一下Header:这里主要放用户的名字就行了,不需要单独的组件去管理(就是直接放一个变量上去,会变化就行啦,不需要组件管理);所以删除;得到下:

6. Footer的实现:

footer主要是输入框:

使用elementUI-input组件:

 绑定一个keyup事件;回车发送消息:(注意:vue2是需要加native修饰符的!!!!

<el-input placeholder="请输入内容" v-model="input" @keyup.enter.native="send"> </el-input>
data() {
    return {
      input:'',
    }
  },
  methods: {
    send(){
      /* 发送消息 */
      console.log(this.input);
      /* 清空输入框 */
      this.input='';
    },
  },

7. Aside的实现

7.1 渲染用户列表;

这里我说明一下啊!我们现在的项目,数据涉及到各个组件间的通信,所以推荐使用Vuex管理数据。我们先将静态页面做好,再将数据迁移到vuex中是最方便的。所以下面的代码的数据,都是在自己的组件内部。使用到vuex,我会特别说明。

<div>
      <el-row style="height:60px">我的信息</el-row>
      <el-row style="height:50px">
        <el-input v-model="keyword" placeholder="搜索好友">
          <el-button slot="append" icon="el-icon-search"></el-button>
        </el-input>
      </el-row>
      <el-row style="height:390px">好友列表</el-row>
  </div>

 如果大家达不到这个效果,可能是css错了,检查一下,一般都是高度问题,复制过来的css样式中,有一个line-height,注意这个。(这个部分主要是页面的布局,可以自己写)

使用 elementUI table组件,配合Avatar 头像组件,搭建出用户列表:

基础数据:(头像是网上百度的地址,练习就不需要下载到本地啦)

方法可以看下,可能有些加密了,就找别的就行了(直接找源码:F12):

 tableData: [{
          name: '王小虎',
          img: 'https://p0.ssl.qhimgs1.com/sdr/400__/t0197ad9742a3e63410.jpg'
        }, {
          name: '郑泷',
          img: 'https://cube.elemecdn.com/0/88/03b0d39583f48206768a7534e55bcpng.png'
        }, {
          name: '小蛮',
          img: 'http://gss0.baidu.com/-fo3dSag_xI4khGko9WTAnF6hhy/zhidao/pic/item/30adcbef76094b36ba49777aa5cc7cd98c109d49.jpg'
        }, {
          name: '张云',
          img: 'http://img.52z.com/upload/news/image/20180111/20180111085521_86389.jpg'
        }]

关键代码:

<el-table :data="tableData" stripe style="width: 100%" :show-header='false'>
        <el-table-column  label="日期">
          <template slot-scope="scope">
            <el-avatar :src="scope.row.img"></el-avatar>
              <span>姓名: {{ scope.row.name }}</span>
          </template>
        </el-table-column>
      </el-table>

 效果:

 完善一下,给个固定高度(跟Aside相同!!!),超过了就有滚动条了;给个样式,去掉姓名,垂直居中:

 7.2 个人信息:

跟用户列表渲染相似:

关键代码:

<div class="myinfo">
        <el-avatar src="http://img.52z.com/upload/news/image/20180111/20180111085521_86389.jpg"></el-avatar>
        <span>在风中飞翔~</span>
      </div>

//css
.myinfo{
  text-align: left;
  vertical-align: middle;
  margin-top: 10px;
  margin-left: 10px;
}
.myinfo span{
  text-align: left;
  vertical-align: middle;
}

效果:

 7.3 搜索框实现

关键代码:(ElementUI  table 组件的事件)

keyword是input框绑定的数据;过滤是table的事件。

:data="tableData.filter(data => !keyword || data.name.toLowerCase().includes(keyword.toLowerCase()))"

 实现效果:

8. vuex的设计:

 之前我们一直关注页面,没有思考vuex的代码,现在补上:

创建store文件夹,创建index.js文件,还是一样的步骤,引入、使用:

import store from './store/index'
new Vue({
  store,
  render: h => h(App),
}).$mount('#app')

index.js

import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

export default new Vuex.Store({
    state: {
        /* 记录登录状态 */
        isLogin:false,
        /* 我的信息 */
        myInfo:{
            img:'',
            name:'',
        },
        /* 别人的信息(特指聊天对象) */
        userInfo:{
            img:'',
            name:'',
        },
        /* 用户列表 */
        userList:[],
        /* 聊天记录 */
        chatMessageList:[],
    },
    mutations: {},
    actions: {},
    modules: {}
})

暂时先这样,后面需要什么数据再添加。 

9. Header实现:

header主要是显示正在聊天的用户名,我们默认可以不显示,点击了用户的时候,将用户名赋给它就行了,这个数据我们现在从vuex来了哦。所以要有函数触发改变vuex的数据变化。点击用户列表:(使用elementUI table事件即可监听)

methods: {
    setUserInfo(row, column, event){
      console.log(row)
    },
  },

 我们直接加这个事件,点击是没有超链接的小手的,加一个css,让它变成小手:

cursor: pointer;

当我们点击这行,可以得到数据:

 将数据赋给vuex:

//vuex mutations 定义:
setUserInfo(state,data){
            state.userInfo=data;
        },

//组件触发:
setUserInfo(row, column, event){
      store.commit('setUserInfo',{name:row.name,img:row.img});
    },

//App引用:
 computed:{
    userInfo(){
      return store.state.userInfo;
    }
  },

实现效果:

点击用户列表,动态改变用户名称(就不放动图了,自己想象哈哈哈)

 10.Main的实现:

到这里,基本的模型已经出现了;还差main主要内容区域,现在实现一下。

main.vue

<template>
  <div class="div1">
      <div>
        <p>1</p>
        <p>1</p>
        <p>1</p>
        <p>1</p>
        <p>1</p>
        <p>1</p>
        <p>1</p>
        <p>1</p>
        <p>1</p>
        <p>1</p>
        <p>1</p>
        <p>1</p>
        <p>1</p>
        <p>1</p>
        <p>1</p>
        <p>1</p>
        <p>1</p>
        <p>1</p>
        <p>1</p>
        <p>1</p>
        <p>1</p>
      </div>
  </div>
</template>

先测试一下能不能自适应,并且超出内容出现滚动条:

 接下来,你就要清楚,你要怎么处理这个消息了!应该v-for循环 p 标签,根据消息的类型,判断居左还是居右:

msgList:[
        {
          username:'',
          list:[{},{},{}],
        }
      ],

当给出这个数据类型的时候,你就能想到,还要根据是不是当前用户的聊天记录,所以有一个username,后面才是聊天内容。 

比较难理解这个点,好好理解一下:

 msgList: [
        {
          username: "王小虎",
          list: [
            {
              type: "",
              time: "",
              msg: "你好啊",
            },
            {
              type: "",
              time: "",
              msg: "你好啊",
            },
            {
              type: "",
              time: "",
              msg: "你好啊",
            },
          ],
        },
      ],

//store数据:
 computed:{
    userInfo(){
      return store.state.userInfo;
    }
  },

 你得先找到你想聊天的那个人,看看你们有没有历史聊天记录,有的话直接渲染,没有就空:

<template>
  <div class="div1">
    <!-- 先循环找到你想要聊天的那个人 -->
    <div v-for="(list, index) in msgList" :key="index">
      <!-- 有聊天记录:循环聊天记录 -->
      <div v-if="list.username==userInfo.name">
        <!-- 再循环显示聊天记录 -->
        <p v-for="(msg, index) in list.list" :key="index">{{msg.msg}}</p>
      </div>
    </div>
  </div>
</template>

效果如下:

 王小虎有聊天记录,郑陇没有。(如果现在给他发消息,就直接push到数组里,下次就有了)

 优化一下页面显示:

 能不能做到这样,就看你上面数组的理解程度了,完整代码如下:

<template>
  <div class="div1">
    <!-- 先循环找到你想要聊天的那个人 -->
    <div v-for="(list, index) in msgList" :key="index">
      <!-- 有聊天记录:循环聊天记录 -->
      <div v-if="list.username==userInfo.name">
        <!-- 再循环显示聊天记录 -->
        <p :class="{'right':msg.type=='my'}" v-for="(msg, index) in list.list" :key="index">
          <el-avatar v-if="msg.type=='user'" :src="userInfo.img"></el-avatar>
          <el-avatar v-if="msg.type=='my'" :src="myInfo.img" style="float:right;"></el-avatar>
          <span class="content">{{msg.msg}}</span>
        </p>
      </div>
    </div>
  </div>
</template>
<script>
import store from "../store/index";
export default {
  data() {
    return {
      msgList: [
        {
          username: "王小虎",
          list: [
            {
              type: "my",
              time: "",
              msg: "你好啊",
            },
            {
              type: "user",
              time: "",
              msg: "你好啊",
            },
            {
              type: "user",
              time: "",
              msg: "你好啊",
            },
          ],
        },
      ],
    };
  },
  computed:{
    myInfo(){
      return store.state.myInfo;
    },
    userInfo(){
      return store.state.userInfo;
    }
  },
};
</script>
<style scoped>
.div1 {
  width: 100%;
}
.div1 P{
  width: 100%;
  height: 50px;
}
.content{
background-color: antiquewhite;
padding: 10px;
border-radius: 10px;
font-weight: bold;
}
.right{
  text-align: right;
}
</style>

11. 总结:

经过上述的步骤,基本上的模型已经出来啦:

 不过数据都是静态数据,下一篇将真正的实现vue-socket.io实现动态数据展示与交互;

难点就是最后一步的不同消息的展示,可以多理解一下。

好了,码了3个多小时,下次更新socket.io的实现。

  • 33
    点赞
  • 125
    收藏
    觉得还不错? 一键收藏
  • 14
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值