我为什么从 Vue 转到 React
编辑:收到很多关于这篇文章的评论后,我意识到我提供的信息并非全部准确。我刚刚发布了这篇文章的更新版本,您可以在这里阅读。出于历史原因,我会保留这篇文章,但请注意,我并不持有所有我在这里提出的观点。
我一直是 VueJS 的忠实粉丝,至今仍认为它是一个潜力巨大的优秀框架。它是我学习的第一个 JS 框架,在我心中永远占据着特殊的位置。事实上,当我第一次开始学习 React 时,我就确信自己永远不会放弃 Vue。它易于学习,使用 Vue CLI,您可以在几分钟内创建一个功能齐全的网站,并使用 Netlify(我博客就是用的)之类的工具轻松部署它。我喜欢.vue
文件的组织方式,HTML、JS 和 CSS 部分各自独立。当我找到一份 React 开发人员的工作时,我发现 React 文件很容易让我感到困惑,因为渲染 JSX 的逻辑很容易失控。我很怀念 Vue 文件,因为如果我想知道 DOM 是什么样子,我只需滚动到文件顶部,就能看到所有与 HTML 相关的内容。
我使用 React 进行专业开发已经大约 7 个月了,在这段时间里,我逐渐领悟了 React 的魅力,并决定从现在开始它将是我的首选 JS 框架(至少,直到它过时,出现更好的框架!欢迎来到前端世界……)。我甚至决定用 React 重写这篇博客,它最初是用 Vue 创建的。我想解释一下 React 吸引我的几个原因。
1. React 中没有魔法
我最喜欢 React 的一点是它真的就是 JavaScript。要创建一个 React 组件,我只需要编写一个常规的 JavaScript 函数,然后返回 JSX 代码即可。就是这样,它真的有效!在我看来,JSX 基本上就是区分函数式 React 组件和普通 JS 函数的唯一标准。即使是 React hooks 也只是函数而已——没错,你只会在 React 中使用它们,但归根结底,它们只是函数而已。它们真的没什么神奇之处。
由于 React 本身就是 JavaScript,我完全不需要猜测代码的来源。相比之下,Vue 中有一些“神奇”的函数和指令,例如$emit
或v-for
。在 React 中,我无需“发出”事件,只需传递一个回调函数即可。这纯粹是 JavaScript,没有任何魔法。在 React 中,我无需记住某些 React 特有的指令来渲染对象列表——我只需使用 JSmap
函数并返回 JSX 即可。
让我们以以下示例为例:一个组件渲染一个用户列表,其中包含一个按钮,用于关注该用户。也许我们可以在社交媒体应用中使用它。以下是 Vue 版本:
<!-- UserComponent.vue -->
<template>
<ul>
<li v-for="user in users" :key="user.id">
{{ user.name }}
<button @click="$emit('followUser', user.id)">Follow</button>
</li>
</ul>
</template>
<script>
export default {
data: () => ({
users: [
{
id: 1,
name: 'Rick',
},
{
id: 2,
name: 'Morty',
},
{
id: 3,
name: 'Summer',
},
],
}),
};
</script>
很简单,对吧?我们渲染了一个列表,users
每个用户名旁边都有一个按钮。点击关注按钮时,followUser
会触发一个事件,并附带我们关注的用户 ID。
这是与 React 相同的想法:
// UserComponent.jsx
import React from 'react';
const users = [
{
id: 1,
name: 'Rick',
},
{
id: 2,
name: 'Morty',
},
{
id: 3,
name: 'Summer',
},
];
export default function ({ onFollowUser }) {
return (
<ul>
{users.map(user => (
<li key={user.id}>
{user.name}
<button onClick={() => onFollowUser(user.id)}>Follow</button>
</li>
))}
</ul>
);
}
我发现 React 实现的美妙之处就在于我之前说过的——它只是恰好能够返回 HTML 的 JavaScript。如果我是新开发者,只要我懂常规的 JS,就能看 React 版本,基本知道是怎么回事。
如果我是一位 Vue 开发者新手,正在考虑 Vue 版本,我必须知道它v-for
是什么,以及它到底$emit
来自哪里。我可能还想了解更多关于data
Vue 文件默认导出属性的信息。这些都是我需要从 Vue 文档中学习的内容。当然,这本身并没有错——作为一名开发者,要掌握所使用的工具,你必须熟悉文档。但当我还是一名 Vue 开发者时,我每天都会打开这些文档。作为一名 React 开发者,当我对某个钩子的功能感到困惑时,我偶尔会查看 React 文档中的 Hooks API 参考。除此之外,我不需要查看React 文档,因为我只是在编写 JavaScript。
2. React 有更好的 TypeScript 支持
正如我在上一篇博文中所述,我最近非常喜欢 TypeScript。我最喜欢 TypeScript 的一点是它在开发过程中能够从 IDE 获得智能感知。处理动态对象(例如网络或数据库响应)时,如果使用常规的 JavaScript,编辑器无法提示这些对象有哪些属性。然而,使用 TypeScript,你只需要为这些响应定义一个类型,然后由于编辑器知道你正在处理的属性,操作这些数据就变得非常容易。再也不用因为意外拼错了属性名而困惑代码崩溃了!
互联网上已经充斥着对 TypeScript 大加赞扬的文章,我就不多说了。总而言之,TypeScript 的扩展性远胜于常规 JavaScript,而且我发现 React 与 TypeScript 的兼容性比 Vue 好得多。
很大一部分原因在于,React 本质上就是 JavaScript,而 Vue 则活在自己的小世界里。创建一个 TypeScript React 应用就像运行 一样简单npx create-react-app my-app --template typescript
,而且一切正常。
现在,Vue CLI 还允许您创建 TypeScript 项目。只需运行vue create my-project-name
,然后您就可以选择创建一个 TypeScript 项目。但是,这样做有几个问题。正如Vue 组合 API RFC中所解释的,让 Vue 真正与 TS 良好配合的唯一方法是使用类组件装饰器,但我并不喜欢这种方式。我在一个类项目中使用了 TS 和 Vue 类组件装饰器,我觉得很难找到好的文档,而且没有足够大的社区以这种方式使用 Vue,让我可以轻松地在网上找到我认为是常见问题的答案。
对于另一个项目,我实际上决定使用实验性的Vue Composition API 插件,这意味着我不必使用我讨厌的类组件,同时仍然可以享受相当不错的 TS 支持。从技术上讲,不建议在生产代码中使用此插件,但我还是用了,因为我真的不想使用类组件。此外,我使用它的项目只会被少数几位古亚述研究人员大量使用,所以我并不太担心它的大规模可扩展性。
值得庆幸的是,组合 API 将在 Vue 3 中默认可用,因此我赞扬 Vue 对 TS 支持的改进。不过,对我来说,React 胜出的关键在于 JSX 中提供的智能感知功能。Vue 的模板部分仍然位于顶部,即使使用了 TS,编辑器也没有很好的错误检查方法。另一方面,由于 React + TS 的 linters 功能在 JSX 中也能很好地工作,因为你只是在 JSX 中编写 JavaScript。
让我们以 TypeScript 为例,在 Vue 和 React 中创建一个简单的计数器应用。这两个应用都会包含一个拼写错误。以下是 Vue 版本(使用 Composition API 插件):
<template>
<div>
<!-- Typo! But ESLint has no idea! -->
<button @click="increaseCouter">Click me</button>
You've clicked the counter {{ counter }} times
<div>
</template>
<script lang="ts">
import { defineComponent, ref, Ref } from "@vue/composition-api";
export default defineComponent({
name: "CounterApp",
setup() {
const counter: Ref<number> = ref(0);
const increaseCounter = (): void => {
counter.value += 1;
}
return {
counter,
increaseCounter
};
}
});
</script>
这是用 React 实现的同一个应用程序:
import React, { useState } from 'react';
const CounterApp = () => {
const [counter, setCounter] = useState(0);
const increaseCounter = (): void => {
setCounter(prevCounter => prevCounter + 1);
};
return (
<div>
{/* Typo! But this time, ESLint spots it for us! */}
<button onClick={increaseCouter}>Click me</button>
You've clicked the counter {counter} times
</div>
);
};
export default CounterApp;
在这两个应用中,“increaseCounter” 的拼写错误为“increaseCouter”。你可以在两个项目中设置 ESLint,但 Vue 项目中的拼写错误无法被检测到。在 React 项目中则不会出现问题,因为 React 本身就是 JavaScript,ESLint 会立即识别出“increaseCouter”未定义。
现在,Vue 确实提供了相当不错的错误信息,所以在这个例子中,当你运行你的应用时,你会收到一条关于“increaseCouter”未定义的错误。然而,一旦你开始处理更复杂的代码,你可能无法总是得到如此即时的反馈。当然,仅仅在 React 中使用 TypeScript 并不能保证你的代码没有 bug。但你可以比使用 Vue 更轻松地自动捕获像上面这样的愚蠢错误。
通过一些配置,实际上有一种方法可以将 JSX 与 Vue 结合使用,从而解决这个问题。但目前似乎还没有一个大型社区在做这件事,所以当你遇到问题时,你可能很难找到答案。在这种情况下,你不妨直接使用 React,因为它开箱即用地支持 JSX。
3. React 更易于测试
当我还是一名 Vue 开发者时,我开始学习测试驱动开发的重要性。我花了很长时间才适应在编写应用程序代码的同时编写测试的思维模式,但现在我已经到了这样的地步:即使是小型的副项目,我也觉得离不开一个像样的测试套件。
我养成这种思维模式的时间,大概是在我开始拥抱 TypeScript 的时候。我发现测试我的 Vue 组件非常困难,即使我用 TypeScript 让它们工作。在使用 Vue Composition API 插件时,我发现Vue Test Utils很多时候无法正确渲染我创建的组件。这对我来说可能并不意外。我怀疑维护 Vue Test Utils 的团队是否过于专注于让测试与 Composition API 插件兼容,毕竟 Composition API 本身就应该随 Vue 3 原生发布。
当你将 Vue 2 的选项 API 与常规 JavaScript 结合使用时,Vue Test Utils 实际上相当不错。然而,当我开始使用 Vuetify(一个非常棒的库)时,我很快就遇到了问题。让 Vue Test Utils 识别 Vuetify 组件有点麻烦,
而且我似乎从未真正弄清楚如何让测试正确地使用 Vue + Vuetify 或 Vue + TypeScript 进行。也许我遗漏了什么。如果是这样,我很想了解一下。
使用 React,我尝试设置单元测试时从未遇到过非常奇怪的错误,即使使用 TypeScript 或Material UI之类的组件库也是如此。再次强调,这一切基本上可以归结为一个事实:React 就是 JavaScript。它没有什么魔法——它的所有依赖项都import
在每个文件中,这使得使用 Jest 进行模拟变得轻而易举。使用 Vuetify 之类的工具,所有组件都“神奇地”可用,这就是为什么我在尝试测试它们时遇到这么多问题的原因。现在,我知道浅层渲染组件可以轻松解决这些问题,但我同意 Kent C. Dodds 的观点,浅层渲染组件并不能真正以应有的方式进行测试。
结论
这篇文章的目的并非说 Vue 不好——事实上,在我使用 Vue 工作的一年半时间里,大部分时间我都对它非常满意,并且仍然认为它是一个非常棒的前端框架。我认为它是一个易于学习的框架,对于 Web 开发者新手来说是一个很好的起点。我之所以选择 React,是基于我自己的经验。正如我提到的,TypeScript 对我来说几乎是必备的,而且我发现它在 React 中比在 Vue 中更容易使用。但对于那些不一定想使用 TypeScript 的人来说,React 可能并没有比 Vue 更明显的优势。
我也坦白承认,我提到的一些 Vue 问题几乎肯定有我不知道的解决方案,而且我愿意学习!以我的经验来看,我发现用 React 解决我遇到的问题比用 Vue 容易得多。归根结底,这篇文章只是代表我个人的观点,并基于我作为一名 Web 开发者所认为的重要因素。拥有不同经验的人可能更喜欢 Vue,这完全没问题。但目前,我还是会坚持使用 React。
文章来源:https://dev.to/brettfishy/why-i-converted-from-vue-to-react-1abn