React 与 Vue 之间的对比,是前端的一大热门话题。
vue 简易上手的脚手架,以及官方提供必备的基础组件,比如 vuex,vue-router,对新手真的比较友好;react 则把这些都交给社区去做,虽然这壮大了 react 的生态链,但新手要弄出一套趁手的方案挺麻烦的,不过好在现在有很多类似 dva 的方案了。
vue 比较讨喜的一点,就是它的数据双向流动在表单开发时特别方便,而 react 在这方面可就麻烦多了。
但是 vue 复杂的 api ,简直让人头大,光是文档说明都几十页了。太多的语法,太多的魔法符号,对进化速度越来越快的前端届来说,就是入手这个框架的最大阻碍。
而相反 react 的 api 数量简直可以忽略不计了,顶多花几小时就能看完官方文档。你只要理解 JavaScript,就能理解 react 的很多行为。react 的很多用法,它的 api 都是符合直觉的,你对它用法的猜测基本都是八九不离十的,这真是大大降低了心智负担。
除此之外,react 的 jsx 语法表达能力更强,还有 hoc 和 hooks 使代码也更容易组织和复用。
虽然我更喜欢 React ,但工作上的需求,还不是要你用什么你就得用什么 😂,所以这个 demo 就当是探索 Vue 的前奏。
之前我还是有用过 vue 的,记得还是 1.0 版本,当时的潮流就是类似 angular 1.x 的 mvvm 方案,数据双向流动。那时的 vue 远没有现在的热度,组件也少,没有 vue-router,没有 vuex,组件之前的通信简直太痛苦了。现在 vue 2.x 比起之前,已经发生了天翻地覆的变化,vue 也在不断向 react 靠拢,而我也只能从头开始学起。
闲话说得有点多,还是赶紧进入主题吧
项目配置
选择 webpack 4 打包和管理,template 引擎使用 pug ,css 预编译是 scss。
webpack.common.js 的配置
// webpack.common.js |
webpack.dev.js 的配置
就是开发服务器 devServer 的配置,监控代码变更。
// webpack.dev.js |
babel.config.js 的配置
module.exports = { |
目录结构
public #公共目录 |
入口和路由
路由文件
下面使用了嵌套路由,使用的是基于 history 的路由,也可以选择基于 hashchange 的路由。
import Vue from 'vue'; |
入口文件
把 router,store 和根组件组合起来
import Vue from 'vue'; |
模块的编写
模版,逻辑代码,样式合成到一个页面也是我欣赏 vue 的一个方面,因为这样你就不需要在多个文件之间反复的切换。
模版 template
pug 就是之前的 jade,它的简洁在复杂的页面下会让 template 清晰不少,最起码会让你少敲代码,这里以 index 页面的部分代码为例。
<template lang="pug"> |
动态创建组件
上面用到了 vue 的 动态创建组件 的概念,什么意思呢?这个组件在当前页面中是不存在的,需要我们触发之后,才开始创建。比如,当你点击某个按钮,才开始加载创建组件,然后填充到页面中来。下面就是动态组件相关功能的编写。
data() { |
javascript 部分
这里就是业务逻辑的部分了,以部分代码为例, 具体的部分参考官方的文档
<script> |
style 部分
使用了 vue 默认的 scoped ,当然最完善的方案是 css-module,配置要复杂一些,当然这要看你项目需求。预编译器使用的是 scss,个人认为比较强大和方便。
<style lang="scss" scoped> |
vuex 的使用
vuex 相比 react 中的 redux,使用起来也更加简单和方便,尽管相比 redux 可能没有那么 “纯”,但好用就行。 vuex 直接把异步的 action 封装进里面,使用 module 将不同组件的状态区分开来。可以说 vuex 的 store 集中了 项目大部分与 状态相关的业务逻辑,这也是 vue 项目的一大关键点。
store
vuex 的 store 和 redux 的 store 一样。
import Vue from 'vue'; |
全局 state 和 mutations
vuex 中的 state 对应 redux 的 state,mutations 则类似 redux 中的 action,其中 mutations 是同步的。
export const state = { |
全局 action 和 getters
vuex 的 aciton 就是将异步的动作封装起来。而redux 得通过 redux-saga 之类的中间件才能实现类似的效果。
import { get, post } from '../common/request'; |
getters 可以看成是对 state 中某些字段的封装
export const visible = state => state.modal.visible; |
modules
随着项目规模的扩展,拆分和模块化都是一个必然。针对某个子模块而设置的 store,它的结构和根 store 一样,module 的 store 最终会合并到根 store 里面。msg 为例的编写方式如下:
import { get, post } from '../../common/request'; |
socket.io 的接入
接着将 websocket 使用起来,让我们实现 好友聊天和分组聊天的功能,socket.io 的介绍可以看我之前的文章 _关于 socket.io 的使用_。
客户端
首先连接服务端的 socket,然后将自身的用户信息注册到 socket.io 服务,这样服务端才知道你是谁,也才能与其他人实行通信。
async created() {// vue 组件创建时建立socket连接 |
服务端
socket.io 对应的服务端部分,逻辑主要包括用户注册,两人聊天,群聊天,当然对应的信息需要保存到数据库。 这里的技巧就是使用变量记录当前所有登录用户的信息。
const auth = require('./auth.js'); |
客户端的启动
首先得编写 client.js,将前端服务启动起来,依然还是使用我们高效的 koa 框架。我这里图省事,和之前的服务端所在同一个根目录下,真正项目会将服务端部分和客户端部分 分离到不同目录或不同的服务器的。
const koa = require('koa'); |
启动服务端和客户端,我们整个 demo 就能运行,主要实现如下功能点:
- 主页面的所有的窗口都可以拖动,关闭
- 可以编辑用户信息,群组信息,每个用户可以新建 3 个群组
- 可以好友聊天,群组聊天
- 搜索用户和群组
- 好友申请和群组申请
- 在线时,可以获得好友上线下线提醒,实时答复用户申请
- 离线时,仍然可以给用户和群组留言,下次登录获得提醒
后续
接下来可以优化和增强的地方,我想到以下几点:
- 使用 nuxt 将 vue 进行服务端渲染 ,进一步提高性能
- node 部分,使用 pm2 进行部署。
源代码: vue_qq