在过去的五年中,我一直是一名 React
工程师。我爱React。我喜欢开发 React
应用程序。我认为它是目前最好的UI框架之一。
但是,在这个领域有一些竞争对手。其中最大的是 Vue.js
。
我以前玩过一些 Vue.js
,但我认为它已经过时了,因为我要深入研究 Vue.js
的工作原理,以及它如何让我的工作更简单。
在深入研究 Vue.js
文档并使用 Vue.js
之后(注意:我不是 Vue.js
专家),在有些方面 Vue.js
比 React
做的更好。
最终我希望 React
受到 Vue.js
所做的这些事情的启发,并且也开始这样做。
不同的理念
Vue.js
和 React
之间的主要区别之一是它们如何称呼自己。
React
把自己描述为 “一个用于构建用户界面的JavaScript库”,而 Vue.js
则把自己描述为“渐进式JavaScript框架”
React
是一个库,Vue.js
是一个框架。我认为这是在很多方面他们处理方式不同的原因。
从历史上看,框架在提供和要求方面更全面、更详尽,而库则更简洁、功能更少,但它们所专注的事情却做得非常好。
单个组件
Vue.js
和 React
都具有作为创建UI的构件的组件。
组件通常由3部分组成:
- 界面(
HTML
) - 行为(
JavaScript
) - 外观(
CSS
)
Vue.js
的概念是 Single File Component
是一种开箱即用的方式来编写涵盖所有3个部分的组件。
<template>
<p>{{ greeting }} World!</p>
</template>
<script>
module.exports = {
data() {
return {
greeting: 'Hello',
};
},
};
</script>
<style scoped>
p {
font-size: 2em;
text-align: center;
}
</style>
你不必是 Vue.js
工程师就能理解这里发生了什么。
React
组件提供了开箱即用的 UI
和 Behavior
,但是样式在很大程度上不受限制:
import React, { useState } from 'react';
function Button() {
const [count, setCount] = useState(0);
return (
<button onClick={() => setCount(count 1)}>
Current count: {count}
<br />
Click me
</button>
);
}
当然,React
有一个非常丰富的社区,因此如果你想包含样式,可以轻松获取 Emotion
或 Styled Components
,它们将填补 Style
的空缺,但是:
- 它不是内置的
- 你必须知道这些库存在才能使用它们。
官方支持的相关库
任何足够大且复杂的UI应用程序都需要两个附加功能来支持它们的实现:
- 路由
- 状态管理
Vue.js
官方支持的库分别覆盖了这两种用例,Vue Router
和 Vuex
。
这些库在 Vue.js
文档页面中明确提到,它们是在 Vue.js
核心中开发和维护的。
它为新的 Vue.js
工程师提供了解决问题的清晰方法,并使他们相信这些库可以持久使用。
拥有第一方支持的库并不限制社区解决方案,但确实为新用户提供了入门解决方案。
风格指南
嗯,我非常希望 React
也有这个,Vue.js
的风格指南 https://v3.vuejs.org/style-guide/
回答了新手可能遇到的许多问题。它提供了有关如何编写 适当的
和 易于访问的
Vue.js
应用程序的最佳实践和指南。
它共享了经过实战使用的经验,以及社区中的最佳实践和模式。
最重要的是:它是由 Vue.js
本身维护和支持的!
类和样式绑定
如上所述,Vue.js
内置了对样式的支持。此外,Vue.js
本质上是内置库类名的。
Classnmes
是一个很棒的库,可以方便地连接和动态构造应用于HTML元素的CSS类名。
在 React
中,你必须知道这个库的存在,然后安装它。
在 Vue.js
中,这只是另一个内置特性。
<div
class="static"
:class="{ active: isActive, 'text-danger': hasError }"
></div>
像这样的数据:
代码语言:javascript复制data() {
return {
isActive: true,
hasError: false
}
}
最终的用户界面将是:
代码语言:javascript复制<div class="static active"></div>
内置此功能真棒。
Vue.js
进一步支持内联样式。Vue.js
和 React
一样,都支持内联样式,但是 Vue.js
超越 React
的地方是它能够自动为需要的 CSS
加上前缀。
来自文档:
当 v-bind:style 使用需要添加浏览器引擎前缀的 CSS property 时,如 transform,Vue.js 会自动侦测并添加相应的前缀。
插槽
React
中的一切都是 prop
。
如果要在 React
组件中渲染多个子代,则只需添加更多 prop
:
function Nav({ left, right }) {
return (
<nav>
<div className="left">{left}</div>
<div className="right">{right}</div>
</nav>
);
}
function App() {
return (
<main>
<Nav left={<Logo />} right={<UserDropdown />} />
</main>
);
}
效果很好,但是有点尴尬,尤其是当 prop
内部的内容变大时。
Vue.js
通过 Slots
采用了不同的方法,我认为它的 API
更加简洁。
<!-- A Vue.js component template named "base-layout" -->
<div class="container">
<header>
<slot name="header"></slot>
</header>
<main>
<slot></slot>
</main>
<footer>
<slot name="footer"></slot>
</footer>
</div>
<!-- When "base-layout" is used -->
<base-layout>
<template v-slot:header>
<h1>Here might be a page title</h1>
</template>
<template v-slot:default>
<p>A paragraph for the main content.</p>
<p>And another one.</p>
</template>
<template v-slot:footer>
<p>Here's some contact info</p>
</template>
</base-layout>
Vue.js
使用 Slots
清楚地指示内容在组件内部的位置。
Vue.js
反复执行的操作为常见任务提供了捷径。在这种情况下,可以使用 Slot
来简化上面的示例:
<base-layout>
<template #header>
<h1>Here might be a page title</h1>
</template>
<template #default>
<p>A paragraph for the main content.</p>
<p>And another one.</p>
</template>
<template #footer>
<p>Here's some contact info</p>
</template>
</base-layout>
指令修饰符
Vue.js
具有称为“指令修饰符”的功能,我认为它真的很酷。
在我谈论指令修饰符之前,让我快速介绍一下指令是什么。
指令 v-
是你在 Vue.js
模板中使用的“带有前缀的特殊属性”。
指令的工作是在其表达式的值发生变化时以反应方式将副作用施加到DOM
例如:
代码语言:javascript复制// If "seen" variable is false then this p tag is not rendered
<p v-if="seen">Now you see me</p>
有针对事件处理程序的指令:
代码语言:javascript复制<!-- full syntax -->
<a v-on:click="doSomething"> ... </a>
<!-- shorthand -->
<a @click="doSomething"> ... </a>
指令还支持修饰符。
这是使用通用指令执行通用任务的非常友好的开发人员方式。
对于事件处理程序指令(v-on),有很多修饰符:
代码语言:javascript复制<!-- the click event's propagation will be stopped -->
<a @click.stop="doThis"></a>
<!-- the submit event will no longer reload the page -->
<form @submit.prevent="onSubmit"></form>
<!-- modifiers can be chained -->
<a @click.stop.prevent="doThat"></a>
<!-- just the modifier -->
<form @submit.prevent></form>
...and more!
如果你想在 React
中执行这样的操作,可以创建一个辅助函数或一个自定义组件。但与指令修饰符相比并不简洁。
我很好奇是否有人可以开发一个 Babel JSX
超集,然后可以编写如下代码:
<form onSubmit.prevent={onSubmit} />
它将转换为:
代码语言:javascript复制React.createElement(form, { onSubmit: preventWrapper(onSubmit) });
这不在 React
的精神范围内,但我仍然认为这是一次超级简洁的生产效率提升。
还有更多的 Vue.js
修饰符。最酷的一些是关键修饰符:
<!-- only call `submit()` when the `key` is `Enter` -->
<input @keyup.enter="submit" />
<input @keyup.page-down="onPageDown" />
非常非常酷
表单输入绑定
当将数据绑定到输入元素时,v-model
指令有一个非常有趣的特性。
从文档中发现,v-model
内部使用了不同的属性,并为不同的输入元素发出了不同的事件:
text
和textarea
元素使用value
属性和input
事件;- 复选框和单选按钮使用
checked
属性和change
事件; select
使用value
用作属性和change
事件。
这样做的好处是,你不需要关心数据是如何同步的,你只需要关心它是如何为你服务的。
让我们比较一下 React
将如何进行这些绑定以及 Vue.js
如何进行绑定:
// Input
////////
// React
<input type="input" value={message} onChange={onChange} />
// Vue.js
<input type="input" v-model="message" />
// Checkboxes and Radiobuttons
////////
// React
<input type="checkbox" checked={message != null} onChange={onChange} />
// Vue.js
<input type="checkbox" v-model="message" />
// Select
////////
// React
<select value={message} onChange={onChange}>
<option>A</option>
</select>
// Vue.js
<select v-model="message">
<option>A</option>
</select>
现在,我要为 React 辩护的一点是,React 鼓励你学习数据实际上是如何设置的以及它是如何变化的。这意味着,如果你曾经用普通JS写过一个表单,你将有更多关于它如何工作的知识,并能够正确地编码它。与Vue.js不同,Vue.js只是将所有用法抽象出来。
自定义指令
像任何好的框架一样,你可以在 Vue.js
中创建自己的自定义指令。
Vue.js
确实注意到“代码重用和抽象的主要形式是组件”,但是为什么自定义指令可能会更好的最好的例子之一是它们的自定义 v-focus
指令自动将输入元素放在 mount
上:
const app = Vue.createApp({})
// Register a global custom directive called `v-focus`
app.directive('focus', {
// When the bound element is mounted into the DOM...
mounted(el) {
// Focus the element
el.focus()
}
})
<input v-focus />
在 React
中,你可能会编写一个自定义组件来完成相同的事情,对于这么轻便的任务而言,这似乎有点繁重。
用 TypeScript 编写
最后但并非最不重要的一点是,最近在 TypeScript
中彻底重写了 Vue.js
。
这意味着它们的 TypeScript
支持是一流的,因为框架本身是用 TypeScript
编写的。
最终,
React
用什么编写并不重要,我也不认为它有什么太大的区别,但看到Vue.js
所拥有的仍然是一个很不错的小事情。
总结
我要放弃 React
并开始专门使用 Vue.js
吗?不。我仍然非常喜欢 React
,坦率地说,我已经非常精通编写 React
应用程序。
但是,我很希望看到 React
从 Vue.js
中汲取一些灵感,并将其中一些很棒的想法整合到 React
中。如果我只能从文中提到的几个点中选择一个,那绝对是 风格指南
。我很乐意看到 React
有一个官方支持和维护的风格指南。