vue使用socket.io聊天室踩坑
阿新 • • 發佈:2019-01-27
此專案的原作者地址連結:https://github.com/Yaer23/vue-chatroom
然後我照著這個在本地寫發現一直在出問題,現在記錄一下出現的問題和解決方法,也是各種試才終於成功
先看專案目錄:
1.安裝socket.io,發現很順利,接下來就是各種錯誤
2.然後啟動服務端js
什麼?沒有socket.io,檢查了一下,原來是我沒有在package.json中配置,開啟服務的js也要在這裡配置一下
以後再出這種問題可以去這裡看看有沒有引入。
3.最笨的解決辦法,這個專案因為之前做的安裝了很多不需要的,還有問題的包,我就直接把modules下的包全刪了再重新安裝,浪費了很長時間
4.然後終於成功啟動了服務端js
5.最坑的來了,使用localhost一直打不開頁面,就像這樣
這裡不知道是什麼問題,最後換了一個寫法用http://127.0.0.1:8081居然可以了
6.終於登陸進來發訊息頁面發現載入不了引數:
不停地報這個錯,也花了我很久去找,我看了很多網站上對這個問題的解決辦法都不一樣,我開始以為我的js寫錯,後來發現不是js,應該先從引入socket.io這裡入手,
開始使用
<script src="https://cdn.bootcss.com/socket.io/2.1.0/socket.io.js"></script>
還是有問題又換成
<script src="http://127.0.0.1:8081/socket.io/socket.io.js"></script>
報錯
最後換成了
<script src="http://localhost:8081/socket.io/socket.io.js"></script>
才行。 還是要多試一下才行,在這些錯誤中也對socket.io的用法有了更深入的理解。
現在把幾個頁面展示一下:
- index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1.0" >
<title>chatroom</title>
<link rel="stylesheet" href="http://at.alicdn.com/t/font_637013_b0ubbuoti59daemi.css">
</head>
<body>
<div id="app"></div>
<script src="http://localhost:8081/socket.io/socket.io.js"></script>
<script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
<!-- built files will be auto injected -->
</body>
</html>
- main.js
// The Vue build version to load with the `import` command
// (runtime-only or standalone) has been set in webpack.base.conf with an alias.
import Vue from 'vue'
import App from './App'
import router from './router'
Vue.config.productionTip = false
/* eslint-disable no-new */
new Vue({
el: '#app',
router,
components: { App },
template: '<App/>'
})
- app.vue
<template>
<div id="app">
<router-view></router-view>
</div>
</template>
<script>
import login from './components/login.vue'
import chatRoom from './components/chatRoom.vue'
export default {
name:'App',
components:{
login,
chatRoom
}
}
</script>
<style>
html,body {
margin: 0;
padding: 0;
}
</style>
- index.js
import Vue from 'vue'
import Router from 'vue-router'
import chatRoom from '@/components/chatRoom'
import login from '@/components/login'
Vue.use(Router)
export default new Router({
routes: [
{
path: '/',
name: 'login',
component: login
},
{
path: '/chatRoom',
name: 'chatRoom',
component: chatRoom
}
]
})
元件:
- chatRoom.vue
<template>
<div id="chatroom">
<div class="header">
<div class="roomUser">
<p>ChatRoom({{clientNum}}users)</p>
</div>
</div>
<div class="body">
<div v-for="(item,index) in msgs" :key="index">
<div v-if="item.msgType=='online'" class="onlineMsg">
<div class="sysTime">{{item.time}}</div>
<div class="online">{{item.username}}上線</div>
</div>
<div v-else-if="item.msgType=='offline'" class="offlineMsg">
<div class="sysTime">{{item.time}}</div>
<div class="online">{{item.username}}下線</div>
</div>
<div v-else-if="item.msgType=='clientMsg'" class="clientMsg">
<div class="sysTime">{{item.time}}</div>
<div v-if="item.username==$route.query.username" class="self">
<div class="bubble">
<div class="chatBubble">{{item.msg}}</div>
<div class="triangle"></div>
</div>
<div class="user">{{item.username}}</div>
</div>
<div v-else class="others">
<div class="user">{{item.username}}</div>
<div class="bubble">
<div class="chatBubble">{{item.msg}}</div>
<div class="triangle"></div>
</div>
</div>
</div>
</div>
</div>
<div class="footer">
<div class="msgInput">
<input v-model="msg" autofocus class="input" type="text" @keydown.enter="send(msg)" placeholder="press Enter to send message" >
</div>
</div>
</div>
</template>
<script>
var moment = require("moment")
import storage from '../../server/storage';
export default {
name:"chatRoom",
data(){
return{
socket:null,
msg:"",
msgs:storage.fetch(),
clientNum:0,
showEmoji:false,
emoji:[]
}
},
mounted:function(){
this.socket = io("http://localhost:8081");
if(this.$route.query.username){
this.socket.emit('online',this.$route.query.username);
}else{
alert("Login First")
this.$router.push("/");
}
this.socket.on('online',data=>{
this.msgs.push({
msgType:"online",
username:data,
time:moment().format("HH:mm:ss")
})
storage.save(this.msgs);
})
this.socket.on('broadcastMsg',data=>{
this.msgs.push({
msgType:"clientMsg",
username:data.username,
msg: data.msg,
time:moment().format("HH:mm:ss")
})
storage.save(this.msgs);
})
this.socket.on('offline',data=>{
this.msgs.push({
msgType:"offline",
username:data,
time:moment().format("HH:mm:ss")
})
storage.save(this.msgs);
})
this.socket.on("clientNum",num=>{
this.clientNum = num
})
},
updated:function(){
this.$nextTick(function(){
var oBody = document.querySelector(".body");
oBody.scrollTop = oBody.scrollHeight;
})
},
methods:{
send:function(data){
var transdata = {
msg:data,
username:this.$route.query.username
};
if(data){
this.socket.emit("msg",transdata);
this.msg="";
}else{
alert('訊息為空!');
}
}
}
}
</script>
<style scoped>
a {
text-decoration: none;
}
a:hover {
color: brown;
}
.chatroom {
width: 400px;
height: 600px;
position: relative;
border: 1px solid #999;
margin: 0 auto;
margin-top: 15px;
}
.header {
background-color: rgb(112, 114, 175);
height: 50px;
display: -webkit-flex;
display: flex;
justify-content: space-between;
align-items: center;
}
.body {
height: 505px;
width: 100%;
overflow: auto;
text-align: center;
}
.iconfont {
font-size: 24px;
}
.logout,
.about {
padding: 7px;
}
.sysTime {
color: #999;
font-size: 13px;
margin-bottom: 3px;
}
.onlineMsg,
.offlineMsg,
.clientMsg{
margin-bottom: 10px;
height: 50px;
width: 100%;
}
.clientMsg{
position: relative;
}
.online,
.offline {
display: inline-block;
height: 23px;
padding-left: 10px;
padding-right: 10px;
border-radius: 3px;
color: #999;
text-align: center;
line-height: 23px;
background-color: rgb(209, 209, 209);
font-size: 16px;
box-sizing: border-box;
}
.self {
position: absolute;
right: 14px;
}
.others {
position: absolute;
left: 14px;
}
.bubble {
display: inline-block;
position: relative;
}
.chatBubble {
height: 30px;
line-height: 30px;
background-color: rgb(198, 205, 243);
font-size: 16px;
color: rgb(58, 58, 58);
border-radius: 10px;
padding-left: 10px;
padding-right: 10px;
}
.self .triangle {
position: absolute;
right: -10px;
top: 10px;
border-left: 10px solid rgb(198, 205, 243);
border-bottom: 10px solid transparent;
}
.others .triangle {
position: absolute;
left: -10px;
top: 10px;
border-right: 10px solid rgb(198, 205, 243);
border-bottom: 10px solid transparent;
}
.self .user {
display: inline-block;
margin-left: 10px;
}
.others .user {
display: inline-block;
margin-right: 10px;
}
.footer {
height: 45px;
width: 100%;
position: absolute;
bottom: 0;
display: -webkit-flex;
display: flex;
}
.emoji {
position: absolute;
left: 10px;
top: 10px;
}
.fade-enter-active, .fade-leave-active {
transition: opacity .5s;
}
.fade-enter, .fade-leave-to {
opacity: 0;
}
.emojiList {
display: inline;
/* width: 400px;
height: 145px; */
position: absolute;
bottom: 30px;
border: 1px solid #ccc;
background-color: rgb(244, 248, 250);
box-sizing: border-box;
padding: 0px;
}
.emojiList li {
display: inline-block;
margin: 0;
cursor: pointer;
width: 24px;
height: 24px;
box-sizing: border-box;
}
.emojiList li:hover {
border: 1px solid #ccc;
}
.msgInput {
position: relative;
width: 100%;
height: 45px;
}
.msgInput .input {
box-sizing: border-box;
width: 350px;
height: 45px;
border: 1px solid #eee;
padding-left: 50px;
background-color: #d1b8b8;
font-size: 18px;
caret-color: rgb(62, 141, 231);
color: rgb(55, 125, 182);
}
</style>
- login.vue
<template>
<div id="container">
<input type="text" v-model="username" @keydown.enter="login" autofocus>
</div>
</template>
<script>
export default {
name:"Login",
data () {
return {
username:""
}
},
methods:{
login(){
if(this.username){
this.$router.push({path: '/chatroom', query:{username:this.username}});
}else{
alert("請輸入您的名字")
}
}
}
}
</script>
<style></style>
js
- app.js
var app = require('http').createServer(),
io = require('socket.io')(app);
app.listen(8081);
PORT=8081,
clientCount=0;
io.on('connection',function(socket){
socket.on('online',function(data){
clientCount++;
io.emit('clientNum',clientCount);
socket.username = data
io.emit('online',data)
console.log('user:'+socket.username+'connected!')
})
socket.on('msg',function(data){
io.emit('broadcastMsg',data);
console.log(JSON.stringify(data)+"發訊息了")
})
socket.on('disconnect',function(){
clientCount--;
io.emit('clientNum',clientCount);
socket.broadcast.emit('offline',socket.username);
console.log(socket.username+'下線了~')
})
})
console.log('listening at :' +PORT)
//
- storage.js
const STORAGE_KEY = 'chatlist';
export default{
fetch:function(){
return JSON.parse(window.sessionStorage.getItem(STORAGE_KEY)||'[]');
},
save:function(item){
window.sessionStorage.setItem(STORAGE_KEY,JSON.stringify(item));
}
}