我使用Vue和React已经很长一段时间了,两个框架上实践代码量都在10万行以上。不得不说都是都很不错的,帮助开发者减少很多工作量,某种框架是现代化Vue和React在两者之间的选择并不像选择苹果或香蕉一样简单,两者在工程实践上的差异让我们逐渐放弃了Vue。此处以不一样的角度对彼此进行深度对比。

常见摇摆问题,观点

首先,我重新谈谈常见对比项目,观点的看法,这些部分内容可以通过一些文章或者Vue官方对比文档查到,主要目的是帮助小白解决入门摇摆问题。如果你反对,欢迎评论区留言Battle,反正我不会回答你这类问题。

Vue或React文档更丰富?

两者都有丰富的文档(包括中文文档),Vue文档,React中文,所以不用担心你四级都过不了,看不懂文档,这都是有眼就行的事〜当然,如果你提前懂点javascript相关知识也是大大滴好,ES6语法更佳,可以在这里跟阮老师学习,免费的电子书。文档和持续进阶不是你在两个框架间做选择的原因。

Vue的话需要记住各种指令,还有属性细节,免不了经常查文档。React相对简单,记住:“函数入口是props,出口是html”就行了。

React学习门槛高?

这个也不是你选择框架的原因,如果这个也可以作为原因的话,我觉得是因为你懒,给自己找了借口。据我自己学习,实践总结,两个框架都很简单,有手就行,有脑就会,不见得会React就比Vue牛逼很多。其中都提供了相应脚手架,方便用户使用:

Vue

npm install -g @vue/cli
vue create my-project

反应

npx create-react-app my-app
cd my-app
npm start

傻瓜式使用,无限div就完事了。

大项目用React,小项目用Vue

这是我以前在华为的时候,内部讨论两个框架对比时下的一个标记。所谓呢?这个就是万精油标注,没有参考意义。你如何定义一个项目是大项目?超过xx万行代码?后端API超过xxx个?无论什么项目,都有做“大”的可能,只要正常运营,你就得持续维护,补充补充的需求。框架的可以替代更为重要。当然我可以这么跟你说,反应适度不适合“小”项目我不知道,但是Vue不适合“大”项目,业务代码超过5万行之后问题明显,后面会详细说这点。

XX大公司也在用Vue,我们跟随就行了

很多新手在入门一些框架,或者选型组件,方案时会看看什么大公司已经用了,避免自己踩坑。当然啦,我也可以滴。但是大公司可能只是“尝鲜”,“实验性” ”使用,这些项目对他们彼此无关紧要,选型失败了,压力给到开发工程师,996纠正就行了,而你,╮(╯▽╰)╭项目和屎一样也得维护下去。

举个选型错误的例子,看看大公司怎么拯救的。

以前在华为做硬件项目的时候,用的原理图软件,那叫一个辣鸡,用着用着总想砸掉电脑。历史问题,选型错误,但无奈很多项目,基础库都在上面,只能硬着头皮搞,迁移的成本太高,软件厂商水平太差,但是华为牛逼啊,把那个软件大改特改,各种内部数据库都集成在上面,各种自开发的辅助工具,还是可以开发出很牛逼的产品,部门做的单板连续11年全球第一。

(PS:以前还用tcl写脚本呢,你也可以试试蛋不蛋疼)- 如果你觉得你能搞定选型错误带来的问题,或者你在华为,那当我们说。

Vue模板简单,React jsx有学习成本

同上。两个都很简单,一学就会。连这点东东都叫学习成本,我只能说:“我不是针对你,我是说在座的各位都是…”(Vue的模板有很多工程实践问题,后面详说。)

性能对比

可以看看这个第三方基准测试,其中都都挺快的。不过我们实践过程中发现有差异,大列表渲染,大量数据加载,不做进一步优化的话Vue明显比React慢。TaskHub这个网站我们以前就是用Vue写的,后来直接迁移到React前端性能大大提高,用户体验有明显的差异(数据结构,后台不变)。

深度对比

本来想简单写写,没想到前面写了那么多了,╮(╯▽╰)╭,下面是重头戏,写写实践过程中发现的问题,两个框架的解决思路。如果你还是小白,下面的一些东西可能没接触过,可以看下这篇文章:【译】通过创建相同的APP,对比React和Vue,切实实现一下,了解基础知识。

市场占比

相关npm下载量见上图,市场已经用脚投票了。看到这里,如果你只想知道选型代表,你可以走了。如果你还说xx大公司在用Vue,跟着就行。可以这么说吧,大公司更多用的是React,用Vue更多的目的是保留相关技术栈能力,多一个选择,避免React许可事件再次发生。

  • React的许可协议到底发生了什么问题?
  • Facebook认怂React专利,但问题依旧没有解决?

当然,尤大也在这里说过,看npm下载量没用,实际使用应该参考devTool的下载量。但是...为啥我打开的很多网站下面这个标都是亮的?

开发生态

客观地说,作为核心团队成员,意识到我们会更偏爱Vue,认为关于某些问题指向用Vue解决会更好。如果没有这点信念,我们也就不会整天如此忙活了。但是在此后,我们想调整地公平和准确地来描述一切。其他的框架也有显着的优点,例如React庞大的生态系统

由Vue官方

生态上的差异是明显的,这点Vue官方也承认的,很多人因为生态这点迁移到React,不过我本人不是很在意,Vue生态也不差,如果说你用了React生态的东西就觉得很牛逼,你的核心也会用,这点并不能给你产品带来多大增值,竞争力还是要靠自己手码出来的好。下面简单带过:

UI组件

两者的周边UI库都挺丰富的,反应稍微多一点,不过这不是选型的关键,自己手写的UI库也不是什么难事,偶尔封装一下原生标签也是很简单的。以前用Vue的时候还没有UI库,手动写了一个功能比较全的UI库,用汇总打包,也就2万行代码左右,有手就行。

dom相关的第三方库

Vue和React都有ref可以操作dom,自己封装一下不是什么难事。可以找找有没别人封装好的,拿来主义。

  • Vue:访问子组件实例或子元素
  • React:Refs和DOM

小程序(划重点)

有小程序开发经验的同学都知道,小程序原生开发是很蛋疼的,通常需要串行框架封装,代码转换。常见的有几个框架:

  • 芋头(React技术栈,推荐使用)
  • wepy(Vue技术栈,强烈不推荐使用)
  • uni-app(Vue技术栈,可以使用)

这些小程序开发框架都是基于Vue或React的二次封装,简化小程序开发。

vue的一些周边库和Vue强绑定,而不是一个独立的js库的形式存在。导致代码难以理解,相关的Bug,问题也带到了二次开发的框架中。

这种强依赖导致的问题会给以后项目升级,迁移带来很多问题。比如vuex作为Vue的官方推荐的状态管理方案,只能在Vue的上面使用,不能在阵营上面使用。Redux的状态管理在阵营上用的多,这个却能用在Vue之上。类似的问题很多,你会发现React周围的东西可以用于Vue,Vue的东西不能用在React上。

如果你觉得这个问题不严重,当你把Vue代码迁移到小程序wepy框架时发现,wepy不支持Vuex(bug异常多),状态管理只能用redux,欲哭无泪。同样的问题,如果你用的是React相关技术栈,反应迁移到Taro小程序框架异常简​​单,而且可以一次性生成微信小程序,支付宝小程序,字节跳动小程序等,代码占用率高。

APP生态

weex,rn这块我没有比较好的实践经验,其中一些生产方案必须慎重考虑。rn比weex成熟这点是明确的。

逻辑代码组织

Vue三种组件写法对比(Js部分)

对象API 29行

import Vue, { PropOptions } from 'vue'interface User {firstName: stringlastName: number
}export default Vue.extend({name: 'YourComponent',props: {user: {type: Object,required: true} as PropOptions<User>},data () {return {message: 'This is a message'}},computed: {fullName (): string {return `${this.user.firstName} ${this.user.lastName}`}}
})

API类17行

import { Vue, Component, Prop } from 'vue-property-decorator'interface User {firstName: stringlastName: number
}@Component
export default class YourComponent extends Vue {@Prop({ type: Object, required: true }) readonly user!: Usermessage: string = 'This is a message'get fullName (): string {return `${this.user.firstName} ${this.user.lastName}`}
}

功能API 25行

import Vue from 'vue'
import { computed, value } from 'vue-function-api'interface User {firstName: stringlastName: number
}interface YourProps {user?: User
}export default Vue.extend({name: 'YourComponent',setup ({ user }: YourProps) {const fullName = computed(() => `${user.firstName} ${user.lastName}`)const message = value('This is a message')return {fullName,message}}
})

React两种组件写法对比(Js部分)

class组件34行

import React, { Component } from 'react';interface P {}interface S {}class Index extends Component<P, S> {constructor(props: Readonly<P>) {super(props);this.state = {};}static defaultProps = {};componentDidMount() {}componentDidUpdate(prevProps: Readonly<P>) {}componentWillUnmount() {}render() {return (<div></div>);}
}export default Index;

函数组件15行

import React, { FC } from "react";interface Props {}const Index: FC<Props> = (props) => {// js 代码return (<div></div>);
};Index.defaultProps = {};export default Index;

在js逻辑部分其中写法没毛病,都需要用到框架特定的生命周期钩子,Vue的类写法最简洁(3种对比),反应的功能写法最清晰(全部写法对比)。这部分不是选择关键,怎么写是个人喜好。

组件内状态管理

Vue使用的是数据对象(数据),反应使用的是状态对象(不可变状态),这点两个框架的设计不同,如下的问题解决思路也不同。

  1. 我如何修改数据?Vue直接将此引用数据对象,直接修改。React使用setState方法修改
  2. 框架如何发现数据被修改?Vue使用es5新方法Object.defineProperty,劫持setter,getter实现数据监听。React,你用了setState,它通过这个函数就知道一些数据变化了。
  3. 我如何发现数据被修改?Vue:使用观察者,或者计算属性发现反应:componentWillUpdate,componentDidUpdate中可以监听变化,或者函数组件的依赖部分插入
  4. 框架何时渲染修改的数据,我如何知道已经渲染好了?Vue:在适当的时候渲染,你通过使用watcher,或者计算属性发现反应:setState调用后在适当的时候重新渲染,并调用相关生命周期钩子

在组件状态管理功能上两者都没有太多槽点,如果要说的话就是Vue watcher写多了代码一堆缩进,比较严重,反应也没好多少。

Vue的写法更加简单,但组件状态很多,需要明确的数据更新逻辑时,反应简单的setState({} ,callback),就搞定了,Vue有点让人摸不到头脑。

Vue项目解决bug和疑难杂症三大定理

没有什么是deep watch解决不了的,有就加立即事件相关,dom相关记得nextTick实在不行,就用setTimeout

(来自某师兄)

React的不可变(immutable)状态在应用复杂时表现出的透明,可测试性更佳。

以上内容对比下降,感觉两者都OKOK的,功能也健全,Vue生态差一点,但是可以自己动手丰衣足食。以下是我们真正弃用Vue的原因。

沃苏艾德布耀布耀德说过:同样的问题,在语言层面上的解决方案才是最佳解决方案。语言生命周期长于框架生命周期

模板语法VS JSX

一部分丢失

Vue的单文件组件,使用<template>,<script>对代码进行分割,直接导致的问题就是丢失。举个例子,你封装了一些常用的函数,在Vue文件中import进来。你这个函数能在template中直接使用吗?

// filter.js 文件
export function isNickname(value) {return /^[\s\S]{1,50}$/.test(value);
}
<template><div>{{ a }}<button @click="a = isNickname('abc')">Test</button>{{ b }}</div>
</template><script>
// eslint-disable-next-line no-unused-vars
import {isNickname} from '../fn/filter';export default {name: 'HelloWorld',props: { msg: String },data: () => {return {a: false,b: 1,c: 1,}},methods: {isNickname1() {return isNickname('abc');}}
}
</script><style scoped></style>

上述代码会报错:

[Vue warn]: Property or method "isNickname" is not defined on the instance but referenced during render

所以你只能将方法定义在methods中,再引用进来。模板语法并不知道你有isNickname这个函数,简单的操作多了3行代码。

模板语法不是图灵完备的,必须转换为js代码(渲染函数),放在组件语境下才行。类似的例子还有很多,你会发现,你写的代码与Vue强绑定了,哪天Vue核心库升级了,你代码也崩溃了。Vue核心库升级了,周边依赖库也得跟着升级。

模板分割

好的代码组织能将常变与不变的部分进行分割解变量

Vue的模板严重限制了这一点。举个例子,前端有个拖放菜单,功能不断增加,而且对于不同的人要显示不同菜单(权限管理)。在Vue中,为了实现html代码(绑定在template)中)的分割,你只能再搞一个组件。在React中,可以直接这样写:

const menu = <div>abc<div>;

可单独做一个组件(低开销函数组件),也可当做变量,放在当前代码中。相对灵活很多。

JSX手写渲染渲染函数自带下面的优势

  • 完整的js功能来构建视图页面,可以使用临时变量,js自带的控制流,以及直接引用当前js作用域中的值
  • 开发工具对jsx的支持比现有vue模板高级(linting,typescript,编译器自动补全)

JSX可以用于Vue可以用于React,就像Redux一样。这种语言是与框架解压缩的。

“虽然模板语法有那么多问题,但是Vue也支持JSX呀。”

我猜到你会这么说,但就像上面所说的,既然我一定要用JSX / TSX,Redux了,那我为什么不用React?

“基于HTML的模板可以将现有的应用逐步迁移到Vue更加容易”

不会更容易,只会更麻烦。首先,下面会说到的模板中无法很好linting,type指示,代码迁移过去很多bug无法及时发现。其次代码迁移很大一部分都是js逻辑的迁移(这个更重要),迁移到vue中,你需要填鸭式细分原始代码,放到计算,心态中,工作量不小且代码和Vue强绑定。最后,原代码类,@ click这些东西,有现代化的编辑器,批量替换成className,onClick不是很简单的事情吗?

打字稿,棉绒支持

这点更是致命,Typescript已成为我们前端开发的必需品。前就能发现大量错误。

而Vue的模板不支持typescript(官方还在增强),在模板上支持要很多“ hack”操作,原始框架更为复杂。Vue.extend对象中编写代码很难有比较好的ts,从而更好的支持Typescript,我们以前都是使用Vue的类写法(参考上文)。前端配合后台放置接口,而很多未提前检查出的错误都出现在模板代码中。

可测试性,重构

Vue需要新建一个.vue文件

<template><div>{{hello}}</div>
</template><script>
export default {name: 'Test',props: {hello: String},created() {console.log(this.hello);}
}
</script><style scoped></style>

React操作都在jsx环境下执行,放的位置随意,写法比模板更容易测试,继承:

function Test(props: { hello: string }) {console.log(props);return <div>{props.hello}</div>
}

Vue与React测试成本的差异明显。React手起刀落,一个函数就搞定了,要测试什么内容清晰可见。类型,属性修正就行了,编辑器自动化。

复杂状态,动作管理

总体状态管理方案选型是很重要的,毕竟95%以上的API对接代码都在这里,这部分代码占位代码很大一部分,可以互换,替代,测试成为选择的关键。

Vue推荐的方案只有将转换的Vuex(Redux迁移到Vue等不算内部)React周边方案有Redux,Mobx等。这些库不会与React有太强的替换(可以独立存在)。两个框架的状态管理思想差不多,都是单向数据流,单例模式(Vuex&Redux)。

威克斯

Vuex的源码不多,可以看这里。可以看到代码中有很多和Vue强绑定的东东,脱离了Vue,这东西就没法用了。你可能会说我就用Vue,什么React不去用不就完了?考虑以下场景:

  • 项目经理要把Vue的代码迁移支持小程序,突然!有的框架不支持Vuex,脑袋嗡嗡嗡叫
  • 项目经理说要设配APP端,突然!一堆臭虫!脑袋嗡嗡叫
  • 项目经理脑抽,要把React项目迁移到Vue,突然!redux!用的还是saga!脑袋嗡嗡叫
  • 状态管理出现静态问题!要写一堆烂码去解决。新人看了脑袋嗡嗡叫

这部分的代码比Vuex源码都多?这些问题都是状态管理库和框架强绑定导致的,框架上的问题也会影响到周边库。

if (version >= 2) {Vue.mixin({ beforeCreate: vuexInit })} else {// override init and inject vuex init procedure// for 1.x backwards compatibility.const _init = Vue.prototype._initVue.prototype._init = function (options = {}) {options.init = options.init? [vuexInit].concat(options.init): vuexInit_init.call(this, options)}}

可以看到,Vue核心升级,这些伴随的库也得升级,测试。在非浏览器环境下运行时,由于Vue(或类Vue框架)的初始化等机制需要体积,会导致相关库,如Vuex不可用,多了一个代码分支,相关代码无法替换,测试,重构负担重。

Redux

Redux是React上比较常用的状态管理方案,其设计思想非常简单(见上图),可以独立使用,相关代码容易迁移到不同平台。衍生出周边替代方案也很多:

  • 重击式
  • redux-promise
  • Redux-Saga
  • 可观察到的

选型可以参考这里&这里,我们用saga比较多,处理静态问题等比较简单,起步多看看文档就可以,也不难。下面这张图可以帮助你理解几个方案之间的关系,利弊权衡。

相关插件也很丰富,参考:Redux Middleware。你会发现很多你想要的东西Vuex都木有!

“既然这样,我在Vue上用Redux就行了”

也行,毕竟这样以后迁移到React会简单点。

万恶之源this指针

写过React函数组件的同学都知道,引用类组件,函数组件少了this指针,代码简化,清晰多余。而这个问题在Vue上更为严重。

有人觉得这是优点,方便使用。等你代码量上去了再来说话。

当项目多人协作的时候,或者承接某人某祖传代码,你不分段搜索,你都不知道这个上面挂了羊头还是狗肉。

  • 这个.ajax
  • 这个.http
  • 这条信息
  • this.wtf…

正如一位网友评论:

那东西就是总体作用域。拿“允许在分成作用域上随便放东西很方便”作为优点的话,和“允许随地大小便会很方便”有什么区别……

写C语言的新手都知道类别变量不要随意用,这满天飞的this,张三读不懂,李四看不懂,IDE也不懂。而且这是官方推荐写法,╮(╯▽╰)╭(说大规模不太准确,应该说是组件作用域)

想起我以前写的Vue UI库,叫SUE-UI,sue〜很快的样子。为了避免以后和其他插件冲突,插件使用都是:

  • this。$ su_message
  • this。$ su_modal
  • 这个。$ su_toast

往事不堪回首啊!

最后

框架功能上,暂时没有发现Vue做的来React做不来的事情,反过来也一样,两个框架都能满足功能需求。工程实践上,由于转换性,代码组织,粗略升级,测试,开拓让我们最终放弃了Vue。

在Vue中你操作的是定义好的对象,React中你操作的是一个函数。所谓前端开发,本质就是在编写下面几个函数。

S = async(A1)
S = sync(A2)
UI = f(S)

显然,阵营对此的抽象更为彻底。

资源获取:

大家点赞、收藏、关注、评论啦 、查看

为什么我们放弃了Vue?Vue和React深度比较相关推荐

  1. 为什么我们放弃了 Vue?Vue 和 React 深度对比

    我使用 Vue 和 React 已经很长一段时间了,两个框架上实践代码量都在 10 万行以上.不得不说两者都是很 nice 的,帮助开发者减少很多工作量,这类框架是现代化前端开发必备的.然而 Vue ...

  2. VUE全家桶 REACT jQuery

    VUE VUE.js是一款JavaScript框架,Vue.js(读音 /vjuː/, 类似于 view) 是一套构建用户界面的渐进式框架. VUE只关注视图层,Vue 的目标是通过尽可能简单的 AP ...

  3. 关于vue,angularjs1,react之间的对比

    1.时间投入的问题:相对于react和angularjs,学习vue的时间成本低,而且容易上手. 2.JSX的可读性比较一般.代码的可读性不如vue,当然,vue也支持jsx,但是vue更提倡temp ...

  4. web前端交流群小程序交流群uni-app交流群vue交流群react交流群

    初心: 前端行业缺乏团结,缺乏有力的互相支撑,前端工程师的话语权其实非常低, 有赖于越来越多的从业者意识到这一点,遂相约几个好友创建此群,望能互助 技术栈: web,前端,小程序,uni-app,vu ...

  5. 适合Vue用户的React教程,你值得拥有

    插槽,在React中没找到?? 在使用Vue的时候,插槽是一个特别常用的功能,通过定义插槽,可以在调用组件的时候将外部的内容传入到组件内部,显示到指定的位置.在Vue中,插槽分为默认插槽,具名插槽和作 ...

  6. 11+实战技巧,让你轻松从Vue过渡到React

    在这个卷神辈出的时代,只是熟练Vue的胖头鱼,已经被毒打过多次了,面试中曾被质疑:"你居然不会React?"我无语凝噎,不知说啥是好. 这篇文章尝试将Vue中一些常见的功能在Rea ...

  7. [vue] vue组件里的定时器要怎么销毁?

    [vue] vue组件里的定时器要怎么销毁? const timer = setInterval(() =>{ // 某些定时器操作 }, 500); // 通过$once来监听定时器,在bef ...

  8. [vue] vue组件会在什么时候下被销毁?

    [vue] vue组件会在什么时候下被销毁? 页面关闭.路由跳转.v-if和改变key值 个人简介 我是歌谣,欢迎和大家一起交流前后端知识.放弃很容易, 但坚持一定很酷.欢迎大家一起讨论 主目录 与歌 ...

  9. [vue] vue组件里写的原生addEventListeners监听事件,要手动去销毁吗?为什么?

    [vue] vue组件里写的原生addEventListeners监听事件,要手动去销毁吗?为什么? 需要,原生DOM事件必须要手动销毁,否则会造成内存泄漏 个人简介 我是歌谣,欢迎和大家一起交流前后 ...

最新文章

  1. 区块链随想:共识不等于信用
  2. 清空缓存的命令_最实用的6个网络命令,网络故障不求人
  3. Home Assistant 安装Samba和SSH server 插件
  4. 集合打印出来的信息不是输入的信息
  5. 一种替代的多生产者方法
  6. Mybatis组成部分
  7. 2019年网络规划设计师下午真题及答案解析
  8. 【leetcode刷题笔记】Sqrt(x)
  9. Redis-数据结构与对象-对象
  10. python数据挖掘系列教程——PySpider框架应用全解
  11. TypeScript接口用法(基础)
  12. [转载] 民兵葛二蛋——第10集
  13. 诡异大阳飙升动因何在
  14. LabVIEW编程运动控制PID入门
  15. TensorRT学习(1):通过pth生成wts文件
  16. [数据结构 算法] A*算法--罗马尼亚度假问题(实验课作业)
  17. Thymeleaf设置固定值属性
  18. Treemily想做封闭版的家族社群,比Geni更迎合华人家庭观念
  19. cesium加载BIM模型
  20. 怀揣美好前行 善良的人终究都会幸福

热门文章

  1. Vue 图片、PDF预览(Blod数据类型)
  2. JsonPath文档
  3. 创维电视 50E6200 找屏参
  4. 看完这篇学不会 Vim 定位操作我跟你姓!
  5. win7 mysql 卸载不干净,大师教您win7系统彻底卸载Mysql数据库的设置办法
  6. GameFramework框架——辅助工具
  7. 线程安全的遍历list
  8. 计算机语言中的次方,浅谈Go语言中的次方用法
  9. matlab相对路径摘抄
  10. 计算机毕业设计Python+uniapp微信签到小程序(小程序+源码+LW)