571
社区成员




- Vue:Vue (读音 /vjuː/,类似于 view) 是一套用于构建用户界面的渐进式框架。与其它大型框架不同的是,Vue 被设计为可以自底向上逐层应用。Vue 的核心库只关注视图层,不仅易于上手,还便于与第三方库或既有项目整合。另一方面,当与现代化的工具链以及各种支持类库结合使用时,Vue 也完全能够为复杂的单页应用提供驱动。
- Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。Vuex 也集成到 Vue 的官方调试工具 devtools extension (opens new window),提供了诸如零配置的 time-travel 调试、状态快照导入导出等高级调试功能。
- 说白了,vuex就是用来管理数据的。
Vuex的核心就是store(仓库),其包含应用中的大部分状态。Vuex 和单纯的全局对象有以下两点不同:
- Vuex的状态存储时响应式的
- store中状态不能直接改变
- 其他组成部分
getter: 类似于 Vue 中的计算属性,根据其他 getter 或 state 计算返回值。
mutation: 一组方法,是改变store中状态的执行者,只能是同步操作。
action: 一组方法,其中可以包含异步操作。
- Socket.io:Socket.IO 是一个面向实时 web 应用的 JavaScript 库。它使得服务器和客户端之间实时双向的通信成为可能。他有两个部分:在浏览器中运行的客户端库,和一个面向Node.js的服务端库。两者有着几乎一样的API。像Node.js一样,它也是事件驱动的.
Socket.IO 主要使用WebSocket协议。但是如果需要的话,Socket.io可以回退到几种其它方法,例如Adobe Flash Sockets,JSONP拉取,或是传统的AJAX拉取,并且在同时提供完全相同的接口。尽管它可以被用作WebSocket的包装库,它还是提供了许多其它功能,比如广播至多个套接字,存储与不同客户有关的数据,和异步IO操作。
Axios:Axios是基于Promise对象实现的可以用于浏览器和node.js的网络请求库。在服务端它使用原生 node.js http 模块, 而在客户端 (浏览器) 则使用 XMLHttpRequest对象。简单的讲就是可以发送get、post请求。
Express:Express 是最流行的 Node 框架,是许多其它流行 Node 框架 的底层库。它提供了以下机制:
- 为不同 URL 路径中使用不同 HTTP 动词的请求(路由)编写处理程序。
- 集成了“视图”渲染引擎,以便通过将数据插入模板来生成响应。
虽然 Express 本身是极简风格的,但是开发人员通过创建各类兼容的中间件包解决了几乎所有的 web 开发问题。这些库可以实现 cookie、会话、用户登录、URL 参数、
POST
数据、安全头等功能。- 设置常见 web 应用设置,比如用于连接的端口,以及渲染响应模板的位置。
- 在请求处理管道的任何位置添加额外的请求处理“中间件”。
<template>
<div>
<el-row type="flex" justify="center">
<el-form
:model="user"
label-width="100px"
:rules="rules"
status-icon
ref="loginForm"
>
<el-form-item label="名称" prop="name">
<el-input v-model="user.name"></el-input>
</el-form-item>
<el-form-item>
<el-button type="primary" icon="el-icon-upload" @click="login">
登录
</el-button>
</el-form-item>
</el-form>
</el-row>
</div>
</template>
登录界面的代码逻辑
<script>
export default {
data() {
return {
user: {},
rules: {
name: [{ required: true, message: "名称不能为空", trigger: "blur" }]
}
};
},
mounted() {
},
methods: {
login() {
this.$refs.loginForm.validate(valid => {
if (valid) {//如果用户名有效(不为空)的话
if (this.user.name) {
this.$store.dispatch("login", this.user).then(() => { //存放数据到vuex里面
this.$notify({//用户登录之后,弹窗出用户登录成功的信息
type: "success",
message: "欢迎," + this.user.name + "!",
duration: 2000
});
this.$router.replace("/chat");//页面的跳转
});
} else {//如果用户名无效(为空)的话,报错
this.$message({
showClose: true,
message: "名称不能为空哦",
type: "error"
});
}
} else {
return false;
}
});
}
}
};
</script>
聊天界面对应UI
<template>
<div>
<div>
<div>
欢迎,{{ user.name }}
<el-button
style="margin-left:20px"
size="mini"
type="plain"
@click="logout"
>退出</el-button
>
</div>
</div>
<div class="fixed-bottom" v-if="user">
<div style="margin-top:15px">
<div style="margin-top:15px" v-for="msg in messages" :key="msg">
<div>{{ msg }}</div>
</div>
</div>
<el-input style="margin-top:15px" @keyup.enter.native="sendMsg" v-model="inputMsg"></el-input>
<el-button style="margin-top:15px" @click="sendMsg">发送</el-button>
</div>
</div>
</template>
<style>
.fixed-bottom {
position: absolute;
bottom: 20px;
}
</style>
前端部分代码逻辑实现
<script>
import io from "socket.io-client";
//fixme
export default {
data() {
return {
messages: [],
inputMsg: "",
//设置一个url和端口
backendUrl: "http://192.168.1.109:9999",
};
},
created() {},
mounted() {
console.log("new io");
let newSocket = io(this.backendUrl); //和后端建立一个socket.io链接
this.$store.commit("connect", newSocket); //把数据存放到vuex中
this.mySocket.on("msg", (data) => {
//前端的监听,监听后端发送的消息
try {
data = JSON.parse(data);
let msg = data.username + ": " + data.content;
this.messages.push(msg); //不能直接修改message,只能用push修改
} catch (error) {
this.$notify(error); //如果发生错误的话直接报错
}
});
this.mySocket.emit("username", this.user.name);
//axios
// this.startPolling()
},
methods: {
logout() {
this.mySocket.disconnect();
this.$store.commit("logout");
this.$router.replace("/");
},
//socket IO version
sendMsg() {
if (this.inputMsg.trim() === "") {
//空字符串直接return,trim在这里的作用是去除字符串前后的空格
return;
}
let msg = {
//存放信息
username: this.user.name,
content: this.inputMsg,
};
try {
this.mySocket.emit("msg", JSON.stringify(msg)); //把前端的信息发送给url里面
this.$message(this.inputMsg);
} catch (error) {
this.$notify(error);
}
this.inputMsg = "";
},
//------------
//axios version
startPolling() {
this.polling = window.setInterval(() => {
console.log("query (axios)");
this.getChats();
}, 1000);
},
addChat(chatObj) {
console.log(chatObj);
// this.messages.push(chatObj);
},
getChats() {
this.axios.get(this.backendUrl + "/chats").then((response) => {
console.log(response.data);
});
// $.get("/chats", (chats) => {
// chats.forEach(addChat)
// })
},
},
computed: {
user() {
return this.$store.state.user;
},
mySocket() {
return this.$store.state.socket;
},
},
destroyed() {
if (this.polling) {
clearInterval(this.polling);
}
},
};
</script>
服务端代码逻辑实现
var express = require('express')
var app = express()
var http = require('http').createServer(app)
var io = require('socket.io')(http)//利用express在服务器端创建一个socket.io对象
var path = require('path')
const cors = require("cors");
const corsOptions = {
origin: '*',
credentials: true,
optionSuccessStatus: 200,
}
//解决一些跨域的问题
app.use(cors(corsOptions))
//通过express设置资源路径
app.get('/', (req, res) => {
res.setHeader('Access-Control-Allow-Origin', '*')
res.sendFile(__dirname + '/index.html')
})
app.use(express.static(path.join(__dirname, '/')));
//监听用户连接事件
io.on('connection', (socket) => {
console.log('---------- start ----------')
socket.on('disconnect', () => {
console.log('---------- end ----------')
})
socket.on("msg", (msg) => {
console.log("message: " + msg);
io.emit('msg', msg)//把监听到的信息发送给所有的socket进程
});
socket.on("username", (name) => {
username = name;
console.log("> user [" + name + "] connected");
});
})
http.listen('9999', () => {
console.log('Listening on: 9999')//监听9999端口
})
总结与展望
本次项目简单地通过Vue + Socket.io + Axios + Express实现了一个简易的在线多人聊天室,但是因为刚接触这些技术,难免有不成熟的地方,未来可以扩展到用户头像、图像传输、用户个人信息修改等等功能,将来有时间可以进行更进一步深入的学习之中!请多指教。
作者:NP208