vue-qq
Vue全家桶+Socket.io+Express/Koa2打造一款網(wǎng)頁版手機(jī)QQ
寫在前面
這個(gè)項(xiàng)目是利用學(xué)習(xí)之余寫的一個(gè)高仿騰訊QQ app的單頁SPA應(yīng)用,整個(gè)項(xiàng)目包含20多個(gè)頁面,涉及實(shí)時(shí)群聊,實(shí)時(shí)私聊,特別關(guān)心,屏蔽對方聊天,添加好友,個(gè)性名片等等,后續(xù)頁面還是開發(fā)中。寫這個(gè)項(xiàng)目主要目的是練習(xí)和熟悉vue全家桶,利用socket.io實(shí)現(xiàn)實(shí)時(shí)聊天。
預(yù)覽
在線預(yù)覽地址:http://lenshen.com:8080/? ? ?(為了體驗(yàn)到最佳的效果,提供了3個(gè)測試賬號,需要賬號才能登陸哦,具體賬號和密碼下面有講)
技術(shù)棧
Vue2.0:實(shí)現(xiàn)前端頁面構(gòu)建
Vuex:實(shí)現(xiàn)不同組件間的狀態(tài)共享
Vue-router:頁面路由切換,實(shí)現(xiàn)單頁的核心
vueg:頁面復(fù)雜場景切換效果
Socket.io:實(shí)現(xiàn)實(shí)時(shí)消息推送
axios:一個(gè)基于Promise的 HTTP 庫,向后端發(fā)起請求
Express、Koa2:開發(fā)環(huán)境使用Express,生產(chǎn)環(huán)境使用Koa2
ES6、ES7、ES8:服務(wù)端和客戶端均使用ES6語法,promise/async/await 處理異步
localStorage:本地保存用戶信息
Webpack:模塊打包,前端項(xiàng)目構(gòu)建工具首選
SASS(SCSS):CSS預(yù)處理語言
Flex:flex彈性布局,簡單適配手機(jī)、PC端
CSS3:CSS3過渡動(dòng)畫及樣式
IScroll:模擬原生app的列表滾動(dòng)效果(ListView)
MySQL:MySQL關(guān)系型數(shù)據(jù)庫持久化數(shù)據(jù)(考慮到表與表之間關(guān)系復(fù)雜,需要多表查詢,最復(fù)雜的時(shí)候是六張表聯(lián)查,用MySQL會(huì)比Mongodb好得多)
jsonp:跨域請求數(shù)據(jù)
pm2:服務(wù)端使用pm2部署,常駐進(jìn)程,比forever好用得多(https://github.com/Unitech/pm2)
使用方式
clone源碼后,先將根目錄下的qq.sql導(dǎo)入到你的MySQL數(shù)據(jù)庫里(可以使用Navicat導(dǎo)入),用戶名為root,登錄密碼為空。啟動(dòng)MySQL服務(wù)。然后使用cnpm install 安裝所有依賴,最后運(yùn)行npm run dev。服務(wù)器部署只需要運(yùn)行npm run pm2(前提是得先全局安裝pm2)。
盡量使用Chrome瀏覽器體驗(yàn)最佳效果。另外提供了三個(gè)測試賬號,默認(rèn)用戶的密碼都是6個(gè)1:
qq:986992484 密碼:111111
qq:986992483 密碼:111111
qq:986992482 密碼:111111
目前已經(jīng)實(shí)現(xiàn)了QQ的核心功能,如消息列表、好友列表、新朋友、好友申請、實(shí)時(shí)群聊、實(shí)時(shí)私聊、聊天設(shè)置、屏蔽對方聊天、特別關(guān)心、會(huì)員等級、個(gè)性名片、添加好友、刪除好友、好友分組、查找用戶、登錄、注銷、切換用戶、右滑顯示滑動(dòng)側(cè)欄等等。后期會(huì)考慮增加更多功能。如果你想體驗(yàn)實(shí)時(shí)聊天的酷炫效果,那么你可以打開兩個(gè)瀏覽器,用上面不同的賬號登錄即可。
截圖
消息頁面

聯(lián)系人頁面

群聊

私聊

分析
服務(wù)端使用ES6語法
不需要使用babel轉(zhuǎn)碼以及一系列的配置,只需要將node升級到V8版本,V8已經(jīng)很好地支持了ES6/ES7/ES8等最新特性,這是目前最好的辦法。升級到V8版本,可以直接到nodejs中文網(wǎng)(http://nodejs.cn/download/) 下載即可,也可以使用NVM切換node版本。
升級到V8后,還不支持通過import/export關(guān)鍵字來導(dǎo)入導(dǎo)出模塊(因?yàn)榉?wù)端已經(jīng)有了CommonJS規(guī)范,如果再使用import/export的話就有點(diǎn)沖突了),如果一定要使用import/export關(guān)鍵字,這時(shí)可以在服務(wù)端的入口文件首行添加以下代碼:
require("babel-core/register")({
? ? ?presets: ['es2015', 'stage-0']
})
require("babel-polyfill")
上面的代碼不可以使用import來導(dǎo)入,必須使用require,同時(shí)需要通過npm安裝babel-core、babel-preset-es2015、babel-preset-stage-0、babel-polyfill等依賴。這樣就可以愉快地使用import/export了。
Socket.io
服務(wù)端(結(jié)合Express/Koa):
// Server
import express from 'express'
import http from 'http'
import socketio from 'socket.io'
const app = express()
const server = http.createServer(app)
const io = socketio(server)
server.listen(3000)
io.on('connection', (socket)=>{
?socket.emit('news', { hello: 'world' })
socket.on('my other event', function (data) {
console.log(data)
})
})
客戶端:
// Client
const socket = io.connect('http://localhost:3000')
socket.on('news', (data)=>{
? ? ? socket.emit('my other event', { my: 'data' })
})
socket.io最核心的兩個(gè)api就是`emit` 和 `on`了 ,服務(wù)端和客戶端都有這兩個(gè)api。通過 `emit` 和 `on`可以實(shí)現(xiàn)服務(wù)器與客戶端之間的雙向通信。
`emit` :發(fā)射一個(gè)事件,第一個(gè)參數(shù)為事件名,第二個(gè)參數(shù)為要發(fā)送的數(shù)據(jù),第三個(gè)參數(shù)為回調(diào)函數(shù)(如需對方接受到信息后立即得到確認(rèn)時(shí),則需要用到回調(diào)函數(shù))。
`on` :監(jiān)聽一個(gè) emit 發(fā)射的事件,第一個(gè)參數(shù)為要監(jiān)聽的事件名,第二個(gè)參數(shù)為回調(diào)函數(shù),用來接收對方發(fā)來的數(shù)據(jù),該函數(shù)的第一個(gè)參數(shù)為接收的數(shù)據(jù)。
服務(wù)端常用API:
`socket.emit()`:向建立該連接的客戶端發(fā)送消息
`socket.on()`:監(jiān)聽客戶端發(fā)送信息
`io.to(socketid).emit()`:向指定客戶端發(fā)送消息
`io.sockets.socket(socketid).emit()`:向指定客戶端發(fā)送消息,新版本用`io.sockets.socket[socketid].emit()` ,數(shù)組訪問`
socket.broadcast.emit()`:向除去建立該連接的客戶端的所有客戶端廣播
`io.sockets.emit()`:向所有客戶端廣播
客戶端常用API:
`socket.emit()`:向服務(wù)端發(fā)送消息
`socket.on()`:監(jiān)聽服務(wù)端發(fā)來的信息