Continue to the previous project Use vuejs to imitate NetEasy Cloud music (for listening and searching) Later, I found that the previous project was very confused simply managed with vue's model, and then I went to see vuex, and planned to do a project practice, but did not want to do a duplicate project. This time, I gave up my face and planned to go out of style.Combining background nodejs, and data baseMongoDB To develop a real-time chat system.This system can be said to be a unified system, but also a dream to realize front-end programmers, to eat everything from front to back.Consider yourself a more complete project.Project Address: https://github.com/hua1995116/webchat Make a star if you feel good.
technology stack
- Front end vue, vue-router, vuex
- Backend nodejs, express
- Database mongodb
- Communications websocket
- Scaffolding tool vue-cli
Structure
├─build
├─config
-models (store mongoose object)
-schemas (schemas model for mongoose)
├─src
│ │ App.vue
main.js (main entrance)
│ ├─assets
-components
-router (vue-router routing)
│ └─store(vuex)
-static (static resource)
Start by building a project with scaffolding tools.Like this:
vue init webpack my-project-name
The structure is roughly like this
OK!Since we're a real-world project, I won't talk much about these configuration issues.Otherwise, it's off the topic again.Otherwise, they will be beaten by the younger brothers and sisters.
Front end
First, look at the page layout under the src directory.(
main.js//main entrance
import Vue from 'vue' import App from './App' import router from './router' import store from './store' // Use museui components 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} })
We chose muse-ui to make the whole project look beautiful, let alone say the UI framework is really beautiful.Don't believe you can see it muse-ui .The rest are the default configurations for scaffolding.
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 } ] })
You can see that there are three routes. That's right. We just wrote three routes. The first one is a chat room with you, and the second one is a chat with our lovely white one, which is ours. Turing Robot .Have a play when you're free.The third piece is our personal center, although it's nothing.But after all, it looks good, oh~forget, we are out of mind, how can we just look at the face?
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')
This sentence is mainly used to connect your current service. When you download the following items, remember to change to your own service and port.Because both Index and Chat are set, you need to change the connection in both Index.vue and Chat to your own service.socket.on() is used to accept messages.socket.emit() is used to send messages.Look here at socket.io you don't understand socket.io .With this, you can interact with the server.The server will be explained later.
store/index.js
state: { //Store User user: { name: '', src: '' }, //Store history messhistory: { infos: [] }, //Store room information for future multi-room use roomdetail: { id: '', users: {}, infos: [] }, //Store robot introductory remarks robotmsg: [{ message: 'Hi~Anything you want to know can ask me', user: 'robot' }], //Chat Page Display Control chattoggle: false, //Login Page Display Control logintoggle: false, //Registration Page Display Control registertoggle: true, //Tip box display control dialog: false, //Tip box content dialoginfo: '' }
Since there is too much control code, please move on to my github address. https://github.com/hua1995116/webchat/
Server Side
Because there is too much webpack code in dev-server.js under build, it is too messy to explain.The main thing to look at is the server side for packaging.The two codes are the same.(
prod.server.js (root)
var express = require('express'); var config = require('./config/index'); var port = process.env.PORT || config.dev.port; var app = express(); var router = express.Router(); //For static display entrance router.get('/',function(req,res,next){ req.url = './index.html'; next(); }); app.use(router); require('./config/routes')(app) /*Introduce*/ var mongoose = require('mongoose') //log file var morgan = require('morgan') //sesstion storage var bodyParser = require('body-parser') var cookieParser = require('cookie-parser') var session = require('cookie-session') //For asynchronous callbacks mongoose.Promise = require('bluebird') global.db = mongoose.connect("mongodb://localhost:27017/vuechat") //Jsonization of data submitted by the server app.use(bodyParser.json()) app.use(bodyParser.urlencoded({extended: true})) //sesstion storage 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) { //Listen for users to post chat content socket.on('message', function (obj) { //Broadcast published messages to all clients io.emit('message', obj) var mess = { username: obj.username, src:obj.src, msg: obj.msg, roomid:'room1' } var message = new Message(mess) //Store incoming messages message.save(function (err, mess) { if (err) { console.log(err) } console.log(mess) }) console.log(obj.username + 'Say:' + obj.msg) }) socket.on('login',function (obj) { users[obj.name] = obj //Used to listen to users in chat rooms io.emit('login', users) }) socket.on('logout',function (name) { delete users[name] //User monitor exits chat room io.emit('logout', users) }) }) //Declare static resource address app.use(express.static('./dist'));
schema model
schema/user.js
var mongoose = require('mongoose') //For md5 encryption var bcrypt = require('bcryptjs') //Number of Salts Added 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() } } }); //Encrypt password 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() }) }) }) //Used to compare passwords correctly 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
This is mainly used for an md5 module, you can view the bcryptjs
schema/message.js
var mongoose = require('mongoose') //Chat Logging Model var MessageSchema = new mongoose.Schema({ username: String, src:String, msg: String, roomid:String, time: { type: Date, default: Date.now() } }) //Static method 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
Server routes
config/routes.js talks about a registered handle, others please go to the project to view
app.post('/user/signup', function (req, res) { //Get Submitted Data 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: 'User name already exists' }) } else { var user = new User(_user) user.save(function (err, user) { if (err) { console.log(err) } res.json({ errno: 0, data: 'login was successful' }) }) } }) })
Mainly used to verify that the user name is duplicated.
That's the core part.For other details, please check my github address (with detailed comments, questions that you don't understand, and suggestions for improvement from your predecessors):
Address: https://github.com/hua1995116/webchat
Online viewing address: http://www.qiufengh.com:8081/#/
npm install -----Installation Dependency npm run dev -----Function npm run build -----Pack node prod.server.js -----Run after packaging //Remember to replace Index.vue and Chat.vue Lower io.connect('http://qiufengh.com:8081') http://qiufengh.com:8081 changed to its project address.
Last few pictures.(