vue+websocket+express+mongodb實戰項目(實時聊天)


博客原文地址:http://www.cnblogs.com/qiufenghua/p/6772949.html,轉載請注明出處。

在原來基礎上增加了多個聊天室以及發送圖片【vue+websocket+express+MongoDB實戰項目(實時聊天)(二)】 
http://www.cnblogs.com/qiufenghua/p/7018886.html
舊版聊天室地址: 
https://github.com/hua1995116/webchat/tree/08ff845a2ca46c27a9024138d5b4173c89dd8056 
新版地址: 
https://github.com/hua1995116/webchat 

----------------------------------------------------------------------------------------------------------------------------------------------------------

繼上一個項目用vuejs仿網易雲音樂(實現聽歌以及搜索功能)后,發現上一個項目單純用vue的model管理十分混亂,然后我去看了看vuex,打算做一個項目練練手,又不想做一個重復的項目,這次我就放棄顏值,打算走心派。結合了后台nodejs,以及數據庫MongoDB來開發了一個實時聊天系統。這個系統可以說是一統江山,也算是實現前端程序員的一個夢了,前后通吃。自認為是一個比全的項目。項目地址:https://github.com/hua1995116/webchat 覺得好的請順手來個star。

技術棧

  • 前端 vue,vue-router ,vuex
  • 后端 nodejs,express
  • 數據庫 mongodb
  • 通訊 websocket
  • 腳手架工具 vue-cli

結構 
├─build 
├─config 
├─models(存放mongoose對象) 
├─schemas(存放mongoose的schemas模型) 
├─src 
│ │ App.vue 
│ │ main.js(主入口) 
│ ├─assets 
│ ├─components (組件) 
│ ├─router(vue-router路由) 
│ └─store(vuex) 
└─static(靜態資源)

首先用腳手架工具構建一個項目。像這樣:

vue init webpack my-project-name

結構大致是這樣的

好!既然我們是實戰項目,我就不多說這些配置問題。不然又跑題了。不然又要被小哥哥小姐姐們打了。

前端

首先看src目錄下的頁面布局。 
main.js// 主入口

import Vue from 'vue'
import App from './App'
import router from './router'
import store from './store'
// 使用museui組件
import MuseUI from 'muse-ui'
import 'muse-ui/dist/muse-ui.css'
Vue.use(MuseUI)
Vue.config.productionTip = false

/* eslint-disable no-new */
new Vue({
  el: '#app',
  router,
  store,
  template: '<App/>',
  components: {App}
})

我們為了讓整個項目看起來漂漂亮亮的,所以選擇了muse-ui,別說,這個UI框架是真的漂亮。不信大家可以看muse-ui。其余都是腳手架的默認配置。

route/router.js

import Vue from 'vue'
import Router from 'vue-router'
import Index from '@/components/Index'
import Robot from '@/components/Robot'
import Home from '@/components/Home'

Vue.use(Router)

export default new Router({
  routes: [
    {
      path: '/',
      name: 'Index',
      component: Index
    },
    {
      path: '/robot',
      name: 'Robot',
      component: Robot
    },
    {
      path: '/home',
      name: 'Home',
      component: Home
    }
  ]
})

大家可以看到一共有三個路由,沒錯,我們就是寫了三塊,第一塊是和大家一起的聊天室,第二塊是和我們可愛的大白聊天,也就是我們的圖靈機器人。有空你也去搞一個耍耍。第三塊就是我們的個人中心,雖然這一塊沒什么東西。但是畢竟好看,哦~忘了,我們是走心的,怎么可以只看臉。

components/Chat.vue

created() {
    const that = this
    this.socket = io.connect('http://qiufengh.com:8081')
    this.socket.on('message', function(obj) {
        that.$store.commit('addroomdetailinfos', obj)
        window.scrollTo(0, 900000)
    })
    this.socket.on('logout', function (obj) {
        that.$store.commit('setusers', obj)
    })
},
this.socket = io.connect('http://qiufengh.com:8081')

  

這一句,主要用於連接你當前的服務,到時候下載后面的項目時,記得改成自己的服務以及端口。因為是在Index和Chat都有設置,所以你需要在Index.vue和Chat里的connect都改成你自己的服務。socket.on()用於接受消息。socket.emit() 用於發送消息。不懂的socket.io的看這里socket.io。有了這個就可以和服務端進行交互。等會講解服務端。

store/index.js

state: {
 //存放用戶
  user: {
    name: '',
    src: ''
  },
  //存放歷史記錄
  messhistory: {
    infos: []
  },
  //存放房間信息,為了方便以后做多房間
  roomdetail: {
    id: '',
    users: {},
    infos: []
  },
  //存放機器人開場白
  robotmsg: [{
    message: 'Hi~有什么想知道的可以問我',
    user: 'robot'
  }],
  //聊天頁面顯示控制
  chattoggle: false,
  //登錄頁面顯示控制
  logintoggle: false,
  //注冊頁面顯示控制
  registertoggle: true,
  //提示框顯示控制
  dialog: false,
   //提示框內容
  dialoginfo: ''
}

由於控制代碼太多,所以之后的內容請大家移步,我的github地址。https://github.com/hua1995116/webchat/

服務器端

由於build下dev-server.js中webpack代碼太多,太雜亂,不易於講解。主要來看看用於打包后的服務器端。兩份代碼是一樣的。 
prod.server.js(根目錄下)

var express = require('express');
var config = require('./config/index');
var port = process.env.PORT || config.dev.port;

var app = express();

var router = express.Router();
//用於靜態展示入口
router.get('/',function(req,res,next){
    req.url = './index.html';
    next();
});

app.use(router);

require('./config/routes')(app)
/*引入*/
var mongoose = require('mongoose')
//日志文件
var morgan = require('morgan')
//sesstion 存儲
var bodyParser = require('body-parser')
var cookieParser = require('cookie-parser')
var session = require('cookie-session')
//用於異步回調
mongoose.Promise = require('bluebird')
global.db = mongoose.connect("mongodb://localhost:27017/vuechat")

//服務器提交的數據json化
app.use(bodyParser.json())
app.use(bodyParser.urlencoded({extended: true}))
//sesstion 存儲
app.use(cookieParser())
app.use(session({
  secret: 'vuechat',
  resave: false,
  saveUninitialized: true
}))

var env = process.env.NODE_ENV || 'development'
if ('development' === app.get('env')) {
  app.set('showStackError', true)
  app.use(morgan(':method :url :status'))
  app.locals.pretty = true
  mongoose.set('debug', true)
}

var server = app.listen(port)

//websocket
// var http = require('http').Server(app);
var io = require('socket.io')(server);
var Message = require('./models/message')
var users = {}
io.on('connection', function (socket) {
  //監聽用戶發布聊天內容
  socket.on('message', function (obj) {
    //向所有客戶端廣播發布的消息
    io.emit('message', obj)
    var mess = {
      username: obj.username,
      src:obj.src,
      msg: obj.msg,
      roomid:'room1'
    }
    var message = new Message(mess)
    //將發送過來的消息進行儲存
    message.save(function (err, mess) {
      if (err) {
        console.log(err)
      }
        console.log(mess)
    })
    console.log(obj.username + '說:' + obj.msg)
  })
  socket.on('login',function (obj) {
    users[obj.name] = obj
    //用於監聽用戶進行聊天室
    io.emit('login', users)
  })
  socket.on('logout',function (name) {
    delete users[name]
    //用戶監聽用退出聊天室
    io.emit('logout', users)
  })
})

//聲明靜態資源地址
app.use(express.static('./dist'));

schema模型

schema/user.js

var mongoose = require('mongoose')
//用於md5加密
var bcrypt = require('bcryptjs')
//加鹽數
var SALT_WORK_FACTOR = 10
var UserSchema = new mongoose.Schema({
  name: {
    unique: true,
    type: String
  },
  password: String,
  src: String,
  meta: {
    createAt: {
      type: Date,
      default: Date.now()
    },
    updateAt: {
      type: Date,
      default: Date.now()
    }
  }
});
//對密碼進行加密
UserSchema.pre('save', function (next) {
  var user = this
  if (this.isNew) {
    this.createAt = this.updateAt = Date.now()
  }
  else {
    this.updateAt = Date.now()
  }
  bcrypt.genSalt(SALT_WORK_FACTOR, function (err, salt) {
    if (err) return next(err)

    bcrypt.hash(user.password, salt, function (err, hash) {
      if (err) return next(err)

      user.password = hash
      next()
    })
  })
})
//用於比較密碼是否正確
UserSchema.methods = {
  comparePassword: function (_password, cb) {
    bcrypt.compare(_password, this.password, function (err, isMatch) {
      if (err) return cb(err)
      cb(null, isMatch)
    })
  }
}

UserSchema.statics = {
  fetch: function (cb) {
    return this
      .find({})
      .sort('meta.updateAt')
      .exec(cb)
  },
  findById: function (id, cb) {
    return this
      .findOne({_id: id})
      .exec(cb)
  }
}

module.exports = UserSchema

這里主要用到一個md5的模塊,可以查看 bcryptjs

schema/message.js

var mongoose = require('mongoose')
//聊天記錄模型
var MessageSchema = new mongoose.Schema({
  username: String,
  src:String,
  msg: String,
  roomid:String,
  time: {
    type: Date,
    default: Date.now()
  }
})
//靜態方法
MessageSchema.statics = {
  fetch: function (cb) {
    return this
      .find({})
      .sort('time')
      .exec(cb)
  },
  findById: function (id, cb) {
    return this
      .findOne({_id: id})
      .exec(cb)
  }
}
module.exports = MessageSchema

服務器的routes 
config/routes.js 講一個注冊的把,其他請前往項目查看

app.post('/user/signup', function (req, res) {
    //獲取提交數據
    var _user = req.body
    console.log(_user)
    User.findOne({name: _user.name}, function (err, user) {
      if (err) {
        console.log(err)
      }
      if (user) {
        res.json({
          errno: 1,
          data: '用戶名已存在'
        })
      } else {
        var user = new User(_user)
        user.save(function (err, user) {
          if (err) {
            console.log(err)
          }
          res.json({
            errno: 0,
            data: '注冊成功'
          })
        })
      }
    })
  })

主要用於驗證用戶名是否重復。

核心部分就講到這里啦,。其他具體的請查看我的github地址(具有詳細的注釋,不明白的可以提問,需要改進的請各位前輩指出): 
地址:https://github.com/hua1995116/webchat 
在線觀看地址:http://www.qiufengh.com:8081/#/

npm install -----安裝依賴
npm run dev -----運行
npm run build -----打包
node prod.server.js -----打包后運行
//記得替換
Index.vue和Chat.vue下的io.connect('http://qiufengh.com:8081')
http://qiufengh.com:8081改成自己的項目地址。

最后上幾張圖。 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM