Web手Q
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 åºï¼å?å?端å?èµ·è¯·æ± - Expressã?Koa2ï¼å¼å?ç¯å¢ä½¿ç¨Expressï¼ç产ç¯å¢ä½¿ç¨Koa2
- ES6ã?ES7ã?ES8ï¼æ?å¡ç«¯å客æ·ç«¯å?使ç¨ES6è¯æ³ï¼promise/async/await å¤ç?弿¥
- localStorageï¼æ¬å°ä¿?åç¨æ·ä¿¡æ?¯
- Webpackï¼æ¨¡å?æå ï¼å?ç«¯é¡¹ç®æå»ºå·¥å ·é¦é
- SASS(SCSS)ï¼CSSé¢å¤ç?è¯è¨
- Flexï¼flexå¼¹æ§å¸å±ï¼ç®å?éé ?ææºã?PC端
- CSS3ï¼CSS3è¿æ¸¡å¨ç»å?æ ·å¼?
- IScrollï¼æ¨¡æåçappçå表æ»å¨ææ(ListView)
- MySQLï¼MySQLå ³ç³»åæ°æ?®åºæ?ä¹ åæ°æ?®ï¼èèå°è¡¨ä¸è¡¨ä¹é´å ³ç³»å¤?æ?ï¼éè¦?å¤è¡¨æ¥è¯¢ï¼æå¤?æ?çæ¶åæ¯å å¼ è¡¨è?æ¥ï¼ç¨MySQL伿¯Mongodb好å¾å¤ï¼
- jsonpï¼è·¨åè¯·æ±æ°æ?®
- pm2ï¼æ?å¡ç«¯ä½¿ç¨pm2é¨ç½²ï¼å¸¸é©»è¿ç¨ï¼æ¯forever好ç¨å¾å¤ï¼https://github.com/Unitech/pm2 ï¼
- nginxï¼æ?å¡ç«¯ä½¿ç¨nginx代ç?端å?£è½¬å?
ä½¿ç¨æ¹å¼?
å å°æ ¹ç®å½ä¸çqq.sqlå¯¼å ¥å°ä½ çMySQLæ°æ?®åºé(å?¯ä»¥ä½¿ç¨Navicat)ï¼ç¨æ·å??为rootï¼ç»å½å¯ç ?为空ãå?¯å¨MySQLæ?å¡ãç¶å?使ç¨cnpm install å®è£ ææä¾?èµ(æå¥½ç¨cnpmå®è£ ï¼å 为项ç®ä¾?èµå¾å¤ï¼npmç¨çæ¯å½å¤çéå?ï¼å¨ç½ç»ä¸?稳å®çæ åµä¸å¾æå?¯è½ä¼å¯¼è´å®è£ 失败ï¼èä¸ä¸è½½é度è¿è¿æ ¢äºå½å çcnpm)ï¼æå?è¿?è¡npm run devãæ?å¡å¨é¨ç½²è¿?è¡é¡¹ç®å?ªéè¦?npm run pm2ï¼è¿æ ·å°±å?¯ä»¥å¸¸é©»è¿ç¨ï¼ä¸?è¿å?æ??æ¯å¾å å ¨å±å®è£ pm2ã
ç®å?å·²ç»?å®ç°äºQQçæ ¸å¿åè½ï¼å¦æ¶æ?¯å表ã?好å?å表ã?æ°æå?ã?好å?ç³è¯·ã?宿¶ç¾¤è?ã?宿¶ç§?è?ã?è?天设置ã?å±?è½å¯¹æ¹è?天ã?ç¹å«å ³å¿ã?ä¼åç级ã?个æ§å??çã?æ·»å 好å?ã?å é¤å¥½å?ã?好å?åç»ã?æ¥æ¾ç¨æ·ã?ç»å½ã?注éã?åæ?¢ç¨æ·ã?å?³æ»æ¾ç¤ºä¾§æ ?ã?å°ç?å®ä½?ã?温度ççãå?æä¼èèå¢å æ´å¤åè½ãå¦æä½ æ³ä½éªå®æ¶è?天çé ·ç«ææï¼é£ä¹ä½ å?¯ä»¥æå¼ä¸¤ä¸ªæµ?è§å¨ï¼ç¨ä¸é?¢ä¸?å?çè´¦å?·ç»å½å?³å?¯ã
æªå¾
- æ¶æ?¯é¡µé?¢
- è?系人页é?¢
- 群è?
- ç§?è?
åæ?
-
æ?å¡ç«¯ä½¿ç¨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å?§ãå?æé¡¹ç®è¿ä¼ç»§ç»æ´æ°åå®åã
å?¯å¨å?妿æ¥ä»¥ä¸é误ï¼è¯·å?èï¼https://github.com/lensh/vue-qq/issues/8
Expression #2 of SELECT list is not in GROUP BY clause and contains nonaggregated column \'qq.b.face\' which is not functionally dependent on columns in GROUP BY clause; this is incompatible with sql_mode=only_full_group_by