;
```
可单独做一个组件(低开销函数组件),也可当做变量,放在当前代码中。相对灵活很多。
JSX 手写 render 渲染函数自带下面的优势
- 完整的 js 功能来构建视图页面,可以使用临时变量、js 自带的控制流、以及直接引用当前 js 作用域中的值
- 开发工具对 jsx 的支持比现有 vue 模板先进(linting、typescript、编译器自动补全)
JSX 可以用于 Vue 可以用于 React,就像 Redux 一样。这种语言是与框架解耦的。
> “虽然模板语法有那么多问题,但是 Vue 也支持 JSX 呀。”
我猜到你会这么说,但就像上面所说的,既然我一定要用JSX/TSX、Redux了,那我为什么不用 React?
> "基于 HTML 的模板使得将已有的应用逐步迁移到 Vue 更为容易"
不会更容易,只会更麻烦。
首先,下面会说到的 template 中无法很好 linting、type 推断,代码迁移过去很多 bug 无法及时发现。其次代码迁移很大部分都是 js 逻辑的迁移(这个更重要),迁移到 vue 中,你需要填鸭式拆分原先代码,放到 computed、menthods 中,工作量不小且代码和 Vue 强绑定。最后,原代码 class、@click 这些东西,有现代化的编辑器,批量 replace 成 className、onClick 不是很简单的事情吗?
## Typescript、linting 支持
> 这点更是致命,[Typescript](https://www.typescriptlang.org/) 已成为我们前端开发必需。类型检测、推断对于代码重构非常重要,哪天后端字段改了,前端可以很方便设配改动,明确知道代码改动点在哪,构建前就能发现大量错误。
而 Vue 的模板不支持 typescript(官方还在增强),在模板上支持要很多“hack”操作,原始框架更为复杂。
Vue.extend 对象中编写代码很难有比较好的 ts 推断,为了更好的支持 Typescript,我们以前都是使用 Vue 的 Class 写法(参考上文)。前端配合后台改动接口,然而很多未提前检查出的错误都出现在模板代码中。
## 可测试性、重构
Vue 需要新建一个.vue 文件
```html
{{hello}}
```
React 操作都在 jsx 环境下执行,放的位置随意,写法比模板更容易测试,迭代:
```javascript
function Test(props: { hello: string }) {
console.log(props);
return
{props.hello}
}
```
Vue 与 React 测试成本的差距明显。React 手起刀落,一个函数就搞定了,要测试什么内容清晰可见。如果要重构 hello 字段,Vue 要记得 template 中的代码也要手动改,React 直接 typescript 类型、属性重构就行了,编辑器自动化。
## 复杂状态、Action 管理
全局状态管理方案选型是很重要的,毕竟 95% 以上的 API 对接代码都在这里,这部分代码占全局代码很大一部分比例,能否复用、重构、测试成为选择的关键。
Vue 推荐的方案只有强耦合的 Vuex(Redux 迁移到 Vue 等不算在内)
React 周边方案有 Redux、Mobx 等。这些库不会与 React 有太强的耦合(可以独立存在)。
两个框架的状态管理思想差不多,都是单向数据流、单例模式(Vuex & Redux)。
### Vuex

Vuex 的源码不多,可以看[这里](https://github.com/vuejs/vuex)。可以看到代码中有很多和 Vue 强绑定的东东,脱离了 Vue,这东西就没法用了。你可能会说我就用 Vue,什么 React 不去用不就完了?考虑以下场景:
- 项目经理要把 Vue 的代码迁移支持小程序,突然!有的框架不支持Vuex,脑袋嗡嗡叫
- 项目经理说要设配 APP 端,突然!一堆Bug!脑袋嗡嗡叫
- 项目经理脑抽,要把 React 项目迁移到 Vue,突然!redux!用的还是 saga!脑袋嗡嗡叫
- 状态管理出现竟态问题!卧槽要写一堆烂码去解决。新人看了脑袋嗡嗡叫
怎么办?!!!这部分的代码比 Vuex 源码都多?
这些问题都是状态管理库和框架强绑定导致的,框架上的问题也会影响到周边库。
```javascript
if (version >= 2) {
Vue.mixin({ beforeCreate: vuexInit })
} else {
// override init and inject vuex init procedure
// for 1.x backwards compatibility.
const _init = Vue.prototype._init
Vue.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-thunk](https://github.com/reduxjs/redux-thunk)
- [redux-promise](https://github.com/redux-utilities/redux-promise)
- [redux-saga](https://github.com/redux-saga/redux-saga)
- [redux-observable](https://redux-observable.js.org/)
选型可以参考[这里](https://zhuanlan.zhihu.com/p/24337401) & [这里](https://juejin.im/post/6844903504427892750),我们用 saga 比较多,处理竟态问题等比较简单,起步多看看文档就可以,也不难。下面这张图可以帮助你理解几个方案之间的关系,利弊权衡。

相关插件也很丰富,参考:[Redux Middleware](https://redux.js.org/advanced/middleware#seven-examples)。你会发现很多你想要的东西 Vuex 都木有!
> “既然这样,我在 Vue 上用 Redux 就行了”
也行,毕竟这样以后迁移到 React 会简单点。
## 万恶之源 this 指针
写过 React 函数组件的同学都知道,相比 class 组件,函数组件少了 this 指针,代码简化、清晰不少。而这个问题在 Vue 上更为严重。全局 this !
> 有人觉得这是优点,方便使用。等你代码量上去了再来说话。
当项目多人协作的时候,或者承接某某祖传代码,你不全局搜索,你都不知道 this 上面挂了羊头还是狗肉。
- this.ajax
- this.http
- this.message
- this.wtf......
正如一位网友评论:
> 那东西就是全局作用域。拿“允许在全局作用域上随便放东西很方便”作为优点的话,和“允许随地大小便会很方便”有什么区别……
写 C 语言的新手都知道全局变量不要随意用,这满天飞的 this,张三读不懂,李四看不懂,IDE 也不懂。而且这是官方推荐写法,╮(╯▽╰)╭(说全局不太准确,应该说是组件作用域)
想起我以前写的 Vue UI 库,叫 SUE-UI,sue~很快的样子。为了避免以后和其他插件冲突,插件使用都是:
- this.$su_message
- this.$su_modal
- this.$su_toast
往事不堪回首啊!
# 最后
框架功能上,暂时没有发现 Vue 做的来 React 做不来的事情,反过来也一样,两个框架都能满足功能需求。
工程实践上,由于耦合性、代码组织灵活性、平滑升级、测试、重构让我们最终放弃了 Vue。
在 Vue 中你操作的是定义好的对象,React 中你操作的是一个函数。所谓前端开发,本质就是在编写下面几个函数。
```
S = async(A1)
S = sync(A2)
UI = f(S)
```
显然,React 对此的抽象更为彻底。
(完)
来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/69981092/viewspace-2710742/,如需转载,请注明出处,否则将追究法律责任。