基于vue+vue-socket.io +express + mongodb + elementUi定義自己的聊天工具

先上成品圖片


chat.PNG

技術(shù)應(yīng)用以及功能介紹

1.前端框架時(shí)用vue2搭建氧猬,基于elementUI
2.vue-socket.io長(zhǎng)連接的使用
3.用戶登陸退出的實(shí)時(shí)顯示
4.聊天數(shù)據(jù)的保存
3.后端使用express + mongoose來對(duì)數(shù)據(jù)進(jìn)行操作,主要包括增刪改查等

上面技術(shù)的使用之前的文章有寫,包括vue+express的使用以及mongoose數(shù)據(jù)庫的連接http://www.reibang.com/p/f50aa818ab66:vue+express的使用
http://www.reibang.com/p/440bb0c9d7f8 :mongoose數(shù)據(jù)庫的連接

下面介紹vue-socket.io長(zhǎng)連接的使用

1.安裝

cnpm i vue-socket.io --save
//這里安裝使用可能會(huì)報(bào)錯(cuò),如果報(bào)錯(cuò)使用vue-socket.io的`^2.1.1-a`版本安裝

2.在main.js引入

import VueSocketio from 'vue-socket.io';
 Vue.use(VueSocketio,'http://localhost:3000/');
//后面的連接為后端地址,這里express啟動(dòng)的地址端口默認(rèn)時(shí)3000

3.在server/bin/www也就是express目錄文件夾下加入以下代碼:

var io = require('socket.io').listen(server.listen(port));

4.定義用戶表結(jié)構(gòu):models文件夾下定義chat.js

var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var chatObj = new Schema({
    groupPepole: String,
    groupTime: String
});
module.exports = mongoose.model('chats',chatObj);
// chatName: String,
// chatTime: String

5.定義內(nèi)容表結(jié)構(gòu)在:models文件夾下定義chatcontent.js

var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var chatconObj = new Schema({
    chatName: String,
    chatTime: String,
    chatContent: String
});
module.exports = mongoose.model('chatcontents',chatconObj);

6.基于experss的增刪改查如下:在routers下定義chat.js,并在app.js下引入
var chatRouter = require('./routes/chat');
app.use('/chat', chatRouter);
chat.js代碼如下:

var express = require('express');
var Router = express.Router();
var chatModel = require('../models/chat');
var chatConModel = require('../models/chatcontent');
// 保存登陸用戶
Router.post('/pepole',function(req,res,next){
      let newDate = new Date();
      let pepoleList = new chatModel({
         groupPepole: req.body.loginName,
         groupTime:  newDate.toLocaleDateString() + ' ' + newDate.toLocaleTimeString()
      });
      pepoleList.save(function(err,doc){
        if(err) {
            res.json({
                states: 0,
                msg: err.message
            });
        }else {
            res.json({
                states: 1,
                msg: '保存成功'
            });
        }
      });  
// 保存用戶發(fā)布內(nèi)容
Router.post('/content',function(req,res,next){
    let newDate = new Date();
    let conList = new chatConModel({
        chatName: req.body.chatName,
        chatContent: req.body.chatContent,
        chatTime: newDate.toLocaleDateString() + ' ' + newDate.toLocaleTimeString()
    });
    conList.save(function(err,doc){
      if(err) {
          res.json({
              states: 0,
              msg: err.message
          });
      }else {
          res.json({
              states: 1,
              msg: '保存成功'
          });
      }
    });  
});
//獲取內(nèi)容并返回
Router.post('/geContentList',function(req,res,next){
    chatConModel.find({}, function(err,doc){
      if(err) {
          res.json({
              states: 0,
              msg: err.message
          });
      }else {
          res.json({
              states: 1,
              msg: doc,
              count:doc.length
          });
      }
    });  
});
//獲取用戶列表
Router.post('/getUserList',function(req,res,next){
    chatModel.find({}, function(err,doc){
      if(err) {
          res.json({
              states: 0,
              msg: err.message
          });
      }else {
          res.json({
              states: 1,
              msg: doc,
              count:doc.length
          });
      }
    });  
});
//退出登陸
Router.post('/out',function(req,res,next){
    let conditions = {
        groupPepole: req.body.loginName
    }
    chatModel.remove(conditions, function (err,doc) {
        if(err) {
            res.json({
                states: 0,
                msg: err.message
            });
        }else {
            res.json({
                states: 1,
                msg: 'doc'
            });
        }
    });
});
module.exports = Router;

下面時(shí)長(zhǎng)連接的使用

1.在server/bin/www下加入以下代碼:

io.sockets.on('connection', (socket) => {
    console.log('鏈接成功了呀'); 
    //監(jiān)聽新用戶加入
     socket.on('login', function(obj){
        //向所有客戶端廣播用戶加入
        io.emit('login', obj);
        // console.log(obj.username+'加入了聊天室');
  });
  socket.on('out', function(obj){
        //向所有客戶端廣播用戶加入
        io.emit('out', obj);
        // console.log(obj.username+'加入了聊天室');
  });
  socket.on('content', function(obj){
        //向所有客戶端廣播用戶加入
        io.emit('content', obj);
        // console.log(obj.username+'加入了聊天室');
    });
});

在前端使用如下:

// 長(zhǎng)連接
        sockets: {
            //不能改,j建立連接自動(dòng)調(diào)用connect
            connect: function() {
                //與socket.io連接后回調(diào)
                console.log("socket connected");
            },
            //服務(wù)端向客戶端發(fā)送login事件
            login: function(value) {
                //監(jiān)聽login(后端向前端emit  login的回調(diào))
                this.userList.push(value);
                console.log(value, 'valuevaluevaluevaluevaluevalue')
            },
            out: function(value) {
                //監(jiān)聽out(后端向前端emit  out的回調(diào))
                this.userList.push(value);
                console.log(value, 'valuevaluevaluevaluevaluevalue')
            },
            content: function(value) {
                //監(jiān)聽out(后端向前端emit  out的回調(diào))
                this.contentList.push(value);
                console.log(value, 'valuevaluevaluevaluevaluevalue')
            }
        },

前端具體頁面如下

<template>
    <div>
        <div id="chat" style="position: relative;">
            <div style="position:fixed;right:100px;top:20px">
                <p>當(dāng)前用戶:{{itemName}}</p>
                <el-button type="danger" style="margin-top:20px" @click="chatLoginOut">退出</el-button>
                
            </div>
            <div style="position:fixed;top:20px;left:20px">
                <el-input v-model="inputUser" placeholder="請(qǐng)輸入用戶名"></el-input>
                <el-button type="primary" style="margin-top:20px" @click="chatLogin">登陸</el-button>
                <p style="margin-top:10px;font-size:14px">在線人數(shù):<span style="color:red">{{userListNew.length}}</span>人</p>
                <p style="margin-top:10px;font-size:14px" v-for="(item,i) in userList" :key="i">
                    <span style="color:red">{{item.groupPepole}}</span>
                    <span v-if="item.type==='in'">上線了</span>
                    <span v-if="item.type==='out'">下線了</span>
                    <span style="padding-left:10px;color:blue;font-size:12px">{{item.groupTime}}</span>
                </p>
                <p></p>
            </div>
            <div class="sidebar">
                <div class="m-card">
                  <header>
                    <img class="avatar" width="40" height="40" alt="Coffce" src="/static/img/1.jpg">
                    <p class="name">群名稱</p>
                   </header>
                   <footer>
                       <input class="search" placeholder="search user...">
                   </footer>
                </div>
                <!--v-component-->
                <div class="m-list">
                    <ul>
                        <!--v-for-start-->
                        <!-- <li>
                            <img class="avatar" width="30" height="30" alt="示例介紹" src="/static/img/2.png">
                            <p class="name">示例介紹</p>
                        </li> -->
                        <li @click="changeName(item.groupPepole)" :class="itemName===item.groupPepole ? 'active' : ''" v-for="(item,i) in userListNew" :key="i">
                            {{item.groupPepole}}
                            <!-- <img class="avatar" width="30" height="30" alt="webpack" src="/static/img/3.jpg"> -->
                            <!-- <p class="name">{{item.groupPepole}}</p> -->
                        </li>
                        <!--v-for-end-->
                    </ul>
                </div>
                <!--v-component-->
             </div>
             <div class="main">
                 <div class="m-message">
                     <ul>
                         <!--v-for-start--><!--v-for-end-->
                         <li style="height:40px" v-for="(item,i) in contentList" :key="i">
                             <span v-if="item.chatName!==itemName" class="contentLeft">{{item.chatName}} : {{item.chatContent}}</span>
                             <span v-if="item.chatName===itemName" class="contentRight">{{item.chatContent}} : {{item.chatName}}</span>
                         </li>
                         <!-- <li style="text-alain:right">121212:23232</li>
                         <li>121212:232323</li> -->
                     </ul>
                 </div>
                 <!--v-component-->
                 <div class="m-text">
                     <textarea v-model="texts" placeholder="點(diǎn)擊按鈕發(fā)送"></textarea>
                     <el-button type="primary" style="margin-top:20px;position: absolute;bottom: 0px;right: 0;" @click="send">發(fā)送</el-button>
                 </div>
                 <!--v-component-->
            </div>
        </div>
    </div>   
</template>  
<style scoped>
.contentRight{
    display: inline-block;
    padding: 8px;
    width: auto;
    background: white;
    position: absolute;
    right: 20px;
}
.contentLeft{
    display: inline-block;
    padding: 8px;
    width: auto;
    background: white;
}
#chat {
    overflow: hidden;
    border-radius: 3px;
}
#chat {
    margin: 20px auto;
    width: 800px;
    height: 600px;
}
#chat .sidebar {
    float: left;
    width: 200px;
    color: #f4f4f4;
    background-color: #2e3238;
}
.m-card {
    padding: 9pt;
    border-bottom: 1px solid #24272c;
}
.m-card .avatar {
    border-radius: 2px;
}
.m-card .avatar, .m-card .name {
    vertical-align: middle;
}
.m-card .name {
    display: inline-block;
    margin: 0 0 0 15px;
    font-size: 1pc;
}
.m-card footer {
    margin-top: 10px;
}
.m-card .search {
    padding: 0 10px;
    width: 100%;
    font-size: 9pt;
    color: #fff;
    height: 30px;
    line-height: 30px;
    border: 1px solid #3a3a3a;
    border-radius: 4px;
    outline: 0;
    background-color: #26292e;
}
.m-list li {
    padding: 9pt 15px;
    border-bottom: 1px solid #292c33;
    cursor: pointer;
    -webkit-transition: background-color .1s;
    transition: background-color .1s;
    position: relative;
}
.m-list .avatar {
    border-radius: 2px;
}
.m-list .name {
    display: inline-block;
    margin: 0 0 0 15px;
    position: absolute;
    top: 19px;
}
.m-list li.active {
    background-color: hsla(0,0%,100%,.1);
}
#chat .main {
    position: relative;
    overflow: hidden;
    background-color: #eee;
}
#chat .m-message {
    height: calc(100% - 10pc);
}
.m-message {
    padding: 10px 15px;
    overflow-y: scroll;
}
#chat .main, #chat .sidebar {
    height: 100%;
}
#chat .m-text {
    position: absolute;
    width: 100%;
    bottom: 0;
    left: 0;
}
.m-text {
    height: 10pc;
    border-top: 1px solid #ddd;
}
.m-text textarea {
    padding: 10px;
    height: 100%;
    width: 100%;
    border: none;
    outline: 0;
    font-family: Micrsofot Yahei;
    resize: none;
}
</style>
<script>
    export default{
        components: {
        },
        data(){
            return{
               inputUser: '',
               userLoginIn: '',
               userList: [],
               userListNew: [],
               counts: '',
               itemName: '',
               texts: '',
               contentList: []
            }
        },
        // 長(zhǎng)連接
        sockets: {
            //不能改,j建立連接自動(dòng)調(diào)用connect
            connect: function() {
                //與socket.io連接后回調(diào)
                console.log("socket connected");
            },
            //服務(wù)端向客戶端發(fā)送login事件
            login: function(value) {
                //監(jiān)聽login(后端向前端emit  login的回調(diào))
                this.userList.push(value);
                console.log(value, 'valuevaluevaluevaluevaluevalue')
            },
            out: function(value) {
                //監(jiān)聽out(后端向前端emit  out的回調(diào))
                this.userList.push(value);
                console.log(value, 'valuevaluevaluevaluevaluevalue')
            },
            content: function(value) {
                //監(jiān)聽out(后端向前端emit  out的回調(diào))
                this.contentList.push(value);
                console.log(value, 'valuevaluevaluevaluevaluevalue')
            }
        },
        mounted(){
            this.getUser();
            this.getCon();
        //    this.$socket.emit('login', {username:'admin'});
        },
        methods: {
            chatLogin() {
               let newDate = new Date();
               // 像后端發(fā)數(shù)據(jù)
               this.$socket.emit('login', {groupPepole:this.inputUser, type: 'in'});
               this.loginIn('in');
               this.getUser();
            },
            chatLoginOut() {
               let newDate = new Date();
               this.$socket.emit('out', {groupPepole:this.itemName, type: 'out'});
               this.loginOut();
               this.getUser();
            },
            changeName(name) {
              this.itemName = name;
            },
            loginIn() {
                //發(fā)送請(qǐng)求,這里我封裝了axios,報(bào)錯(cuò)的話可以用原生的axios請(qǐng)求
                let paramRegist = {
                    type: 'post',
                    path: '/chat/pepole',
                    datas: {
                        loginName: this.inputUser
                    }
                }
                this.$store.dispatch(paramRegist).then(res=>{
                    this.$message({
                    message: res.data.msg,
                    type: 'success'
                    });
                });
            },
            loginOut() {
                let paramRegist = {
                    type: 'post',
                    path: '/chat/out',
                    datas: {
                        loginName: this.itemName
                    }
                }
                this.$store.dispatch(paramRegist).then(res=>{
                    // this.$message({
                    // message: res.data.msg,
                    // type: 'success'
                    // });
                });
            },
            send() {
                this.$socket.emit('content', {chatName:this.itemName, chatContent: this.texts});
                let paramRegist = {
                    type: 'post',
                    path: '/chat/content',
                    datas: {
                        chatName: this.itemName,
                        chatContent: this.texts
                    }
                }
                this.$store.dispatch(paramRegist).then(res=>{
                    // this.contentList = res.data.msg;
                });
            },
             getUser() {
                let paramRegist = {
                    type: 'post',
                    path: '/chat/getUserList',
                    datas: {
                    }
                }
                this.$store.dispatch(paramRegist).then(res=>{
                    this.userListNew = res.data.msg;
                    this.itemName = this.userListNew[0].groupPepole
                });
            },
            getCon() {
                let paramRegist = {
                    type: 'post',
                    path: '/chat/geContentList',
                    datas: {
                    }
                }
                this.$store.dispatch(paramRegist).then(res=>{
                    this.contentList = res.data.msg;
                });
            }
        }

    }
</script>

這個(gè)就時(shí)實(shí)現(xiàn)簡(jiǎn)單的聊天工具,git地址如下https://github.com/a1218331130/vueBlog

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末纵东,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子啥寇,更是在濱河造成了極大的恐慌篮迎,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,406評(píng)論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件示姿,死亡現(xiàn)場(chǎng)離奇詭異甜橱,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)栈戳,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,732評(píng)論 3 393
  • 文/潘曉璐 我一進(jìn)店門岂傲,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人子檀,你說我怎么就攤上這事镊掖。” “怎么了褂痰?”我有些...
    開封第一講書人閱讀 163,711評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵亩进,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我缩歪,道長(zhǎng)归薛,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,380評(píng)論 1 293
  • 正文 為了忘掉前任匪蝙,我火速辦了婚禮主籍,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘逛球。我一直安慰自己千元,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,432評(píng)論 6 392
  • 文/花漫 我一把揭開白布颤绕。 她就那樣靜靜地躺著幸海,像睡著了一般祟身。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上物独,一...
    開封第一講書人閱讀 51,301評(píng)論 1 301
  • 那天袜硫,我揣著相機(jī)與錄音,去河邊找鬼议纯。 笑死,一個(gè)胖子當(dāng)著我的面吹牛溢谤,可吹牛的內(nèi)容都是我干的瞻凤。 我是一名探鬼主播,決...
    沈念sama閱讀 40,145評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼世杀,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼阀参!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起瞻坝,我...
    開封第一講書人閱讀 39,008評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤蛛壳,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后所刀,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體衙荐,經(jīng)...
    沈念sama閱讀 45,443評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,649評(píng)論 3 334
  • 正文 我和宋清朗相戀三年浮创,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了忧吟。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,795評(píng)論 1 347
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡斩披,死狀恐怖溜族,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情垦沉,我是刑警寧澤煌抒,帶...
    沈念sama閱讀 35,501評(píng)論 5 345
  • 正文 年R本政府宣布,位于F島的核電站厕倍,受9級(jí)特大地震影響寡壮,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜讹弯,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,119評(píng)論 3 328
  • 文/蒙蒙 一诬像、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧闸婴,春花似錦坏挠、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,731評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽对竣。三九已至,卻和暖如春榜配,著一層夾襖步出監(jiān)牢的瞬間否纬,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,865評(píng)論 1 269
  • 我被黑心中介騙來泰國打工蛋褥, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留临燃,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,899評(píng)論 2 370
  • 正文 我出身青樓烙心,卻偏偏與公主長(zhǎng)得像膜廊,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子淫茵,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,724評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容

  • 金秋九月爪瓜,艷陽高照; 秋風(fēng)微微匙瘪,波光粼粼铆铆。 彩旗飄飄,鑼鼓喧天丹喻; 舞龍弄獅薄货,助喊吶威。 河水兩岸碍论,人群攢動(dòng)菲驴; 壯士...
    五柳亦閱讀 238評(píng)論 0 1
  • 首因效應(yīng)由美國心理學(xué)家洛欽斯首先提出的赊瞬,也叫首次效應(yīng)、優(yōu)先效應(yīng)或第一印象效應(yīng)贼涩,指交往雙方形成的第一次印象對(duì)今后交往...
    天涯若有鄰閱讀 2,849評(píng)論 0 1
  • 今天我們來談?wù)劵鸺倥男赂琛禠ight》巧涧。 這首歌不知道為什么,十分觸動(dòng)吧遥倦。像是寫了我的青春谤绳,初...
    木華十樺閱讀 396評(píng)論 0 0
  • 閱讀啟智 伴我成長(zhǎng) 稚嫩的聲音在我們的小口中發(fā)出,一陣陣?yán)衫实淖x書聲袒哥,響徹在教室內(nèi)缩筛、課堂外、家庭中....
    史文才閱讀 739評(píng)論 0 0