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



