1. 程式人生 > >vue使用socket.io聊天室踩坑

vue使用socket.io聊天室踩坑

此專案的原作者地址連結: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));
  }
}