1. 程式人生 > >Vue全家桶+Socket.io+Express/Koa2打造網頁版手機QQ

Vue全家桶+Socket.io+Express/Koa2打造網頁版手機QQ

Vue全家桶+Socket.io+Express/Koa2打造的網頁版手機QQ(web app),高仿手機QQ7.1.0版本。為了方便大家學習,現在IP定位介面和實時氣溫介面也開放了!介面請在原始碼中檢視。

預覽

線上預覽地址:https://qq.lenshen.com (儘量使用Chrome瀏覽器體驗最佳效果,另外提供了3個測試賬號,需要賬號才能登入哦)

三個測試賬號如下:

  • qq:986992484 密碼:111111

  • qq:986992483 密碼:111111

  • qq:986992482 密碼:111111

技術棧

  • Vue2.0:實現前端頁面構建
  • Vuex:實現不同元件間的狀態共享
  • Vue-router:頁面路由切換,實現單頁的核心
  • vueg:頁面複雜場景切換效果
  • Socket.io:實現實時訊息推送
  • axios:一個基於 Promise 的 HTTP 庫,向後端發起請求
  • ExpressKoa2:開發環境使用Express,生產環境使用Koa2
  • ES6ES7ES8:服務端和客戶端均使用ES6語法,promise/async/await 處理非同步
  • localStorage:本地儲存使用者資訊
  • Webpack:模組打包,前端專案構建工具首選
  • SASS(SCSS):CSS預處理語言
  • Flex:flex彈性佈局,簡單適配手機、PC端
  • CSS3:CSS3過渡動畫及樣式
  • IScroll:模擬原生app的列表滾動效果(ListView)
  • MySQL:MySQL關係型資料庫持久化資料(考慮到表與表之間關係複雜,需要多表查詢,最複雜的時候是六張表聯查,用MySQL會比Mongodb好得多)
  • jsonp:跨域請求資料
  • nginx:服務端使用nginx代理埠轉發

使用方式

先將根目錄下的qq.sql匯入到你的MySQL資料庫裡(可以使用Navicat),使用者名稱為root,登入密碼為空。啟動MySQL服務。然後使用cnpm install 安裝所有依賴(最好用cnpm安裝,因為專案依賴很多,npm用的是國外的映象,在網路不穩定的情況下很有可能會導致安裝失敗,而且下載速度遠遠慢於國內的cnpm),最後執行npm run dev。伺服器部署執行專案只需要npm run pm2,這樣就可以常駐程序,不過前提是得先全域性安裝pm2。

目前已經實現了QQ的核心功能,如訊息列表、好友列表、新朋友、好友申請、實時群聊、實時私聊、聊天設定、遮蔽對方聊天、特別關心、會員等級、個性名片、新增好友、刪除好友、好友分組、查詢使用者、登入、登出、切換使用者、右滑顯示側欄、IP地理定位、實時氣溫等等。後期會考慮增加更多功能。如果你想體驗實時聊天的酷炫效果,那麼你可以開啟兩個瀏覽器,用上面不同的賬號登入即可。

截圖

  • 訊息頁面

  • 聯絡人頁面

  • 群聊

  • 私聊

分析

  • 服務端使用ES6語法

不需要使用babel轉碼以及一系列的配置,只需要將node升級到V8版本,V8已經很好地支援了ES6/ES7/ES8等最新特性,這是目前最好的辦法。升級到V8版本,可以直接到nodejs中文網(http://nodejs.cn/download/) 下載即可,也可以使用NVM切換node版本。

升級到V8後,還不支援通過import/export關鍵字來匯入匯出模組(因為服務端已經有了CommonJS規範,如果再使用import/export的話就有點衝突了),如果一定要使用import/export關鍵字,這時可以在服務端的入口檔案首行新增以下程式碼:

require("babel-core/register")({
	presets: ['es2015', 'stage-0']
})
require("babel-polyfill")

上面的模組不可以使用import來匯入,必須使用require,同時需要通過npm安裝babel-core、babel-preset-es2015、babel-preset-stage-0、babel-polyfill等依賴。這樣就可以愉快地使用import/export了。

服務端程式碼片段如下:

// ES7 async/await
import express from 'express'
import login from '../../controller/login'

const loginRouter = express.Router()

loginRouter
	.get('/:user/:pwd', async(req, res) => { // 登入
		const result = await login.login(req, res)
		res.json(result)
	})

export default loginRouter
  • Socket.io

服務端(結合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
<script src="http://localhost:3000/socket.io/socket.io.js"></script>
<script>
  const socket = io.connect('http://localhost:3000')
  socket.on('news', (data)=>{
    socket.emit('my other event', { my: 'data' })
  })
</script>

socket.io最核心的兩個api就是emit 和 on了 ,服務端和客戶端都有這兩個api。通過 emit 和 on可以實現伺服器與客戶端之間的雙向通訊。

emit :發射一個事件,第一個引數為事件名,第二個引數為要傳送的資料,第三個引數為回撥函式(如需對方接受到資訊後立即得到確認時,則需要用到回撥函式)。

on :監聽一個 emit 發射的事件,第一個引數為要監聽的事件名,第二個引數為回撥函式,用來接收對方發來的資料,該函式的第一個引數為接收的資料。

服務端常用API:

socket.emit():向建立該連線的客戶端傳送訊息

socket.on():監聽客戶端傳送資訊

io.to(socketid).emit():向指定客戶端傳送訊息

io.sockets.socket(socketid).emit():向指定客戶端傳送訊息,新版本用io.sockets.socket[socketid].emit() ,陣列訪問

socket.broadcast.emit():向除去建立該連線的客戶端的所有客戶端廣播

io.sockets.emit():向所有客戶端廣播

客戶端常用API:

socket.emit():向服務端傳送訊息

socket.on():監聽服務端發來的資訊

FAQ

若使用的過程中遇到問題,可以加官方群交流:611212696。

如果覺得不錯,就毫不吝嗇地給個star吧。後期專案還會繼續更新和完善。