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. 项目说明:本项目基于vue2与cli3,使用vue-socket
目录
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的实现。
更多推荐
所有评论(0)