Vue.js battle React

React:a declarative, efficient, and flexible JavaScript library for building user interfaces.(用于构建用户界面的声明式、高效和灵活的 JavaScript 库。)

Vue:a progressive, incrementally-adoptable JavaScript framework for building UI on the web.(用于在 web 上构建 UI 的渐进式、可逐步采用的 JavaScript 框架。)

亮点

  • 都采用类似的方法来实现相同的目标。例如:灵活、高效构建 web UI。
  • React 以 javascript 为中心,而 Vue 使用混合的 HTML 模板/JS。
  • React 使用一种主动修改状态更新(state)的模型,Vue 通过观察(observe)响应数据。
  • Vue 有许多内置的功能,React 更为灵活且比较依赖其社区。

语言方式

众所周知,Vue3.0 已经发布,composition API似乎是 Vue 的发展方向。

Vue 和 React 之间有明显的相似之处:Vue 组件选项 API 类似于 React 的类组件;而 Vue 3 的composition API类似于 React hooks。

// UserProfile.vue
<div>
  <div>{{ id }}</div>
  <Avatar v-if="showAvatar" :id="id" />
  <UserBody v-if="user" :user="user" />
  <button @click="$emit('follow-click')">Follow</button>
</div>
defineComponent({
  props: {
    id: { type: String },
    showAvatar: { type: Boolean },
  },
  setup(props) {
    const {id} = toRefs(props);
    const user = ref(undefined);
    function updateUser() {
      fetchUser(id.value).then(data => {
        user.value = data;
      });
    }
    onMounted(updateUser);
    watch(id, updateUser);
    return {user};
  }
})
// React
function UserProfile({
  id,
  showAvatar,
  onFollowClick,
}: {
  id: string,
  showAvatar: boolean,
  onFollowClick: () => void,
}) {
  const [user, setUser] = React.useState(undefined)
  React.useEffect(() => {
    fetchUser(id).then(setUser)
  }, [id])
  return (
    <div>
      <div>{id}</div>
      {showAvatar ? <Avatar id={id} /> : null}
      {user !== undefined ? <UserBody user={user} /> : null}
      <button onClick={onFollowClick}>Follow</button>
    </div>
  )
}
// React
function UserProfile({
  id,
  showAvatar,
  onFollowClick,
}: {
  id: string,
  showAvatar: boolean,
  onFollowClick: () => void,
}) {
  const [user, setUser] = React.useState(undefined)
  React.useEffect(() => {
    fetchUser(id).then(setUser)
  }, [id])
  return (
    <div>
      <div>{id}</div>
      {showAvatar ? <Avatar id={id} /> : null}
      {user !== undefined ? <UserBody user={user} /> : null}
      <button onClick={onFollowClick}>Follow</button>
    </div>
  )
}

对于 Vue,HTML 模板是灵魂,模板在构建时被处理成 JavaScript。可以通过Vue Template Explorer(https://vue-next-template-explorer.netlify.app/)查看模板是如何编译成 JS 的。

<div>Hello World!</div>

// 编译后
import {
  createVNode as _createVNode,
  openBlock as _openBlock,
  createBlock as _createBlock,
} from 'vue'

export function render(_ctx, _cache, $props, $setup, $data, $options) {
  return _openBlock(), _createBlock('div', null, 'Hello World!')
}

JSX 则是 React 的语法糖。不少初学者觉得JSX写起来不舒服,后来就真香了,因为真的很灵活丫

从正反两面来说

Vue 模板语法的一个优点是,由于它的限制性更强,编译器能够执行更多的优化,例如分离静态模板内容以避免重新渲染。

而 React 做类似的工作需要借助 Babel 插件完成。理论上,Vue 可以对模板语法进行更多的优化。

Vue 模板的一个缺点是,有时JavaScript 的表现力被严重忽略,甚至是必要的(对比使用 JSX 的感受来说)。在这种情况下,官方推荐使用render函数,也可以通过更详细的createElement或 JSX。

如果使用 React hooks,React 组件只是函数,所有的逻辑都存在在这个函数里面。Vue 将组件定义从模板(或渲染函数)分离,使用composition API,组件定义在一个setup函数里面。有一个很明显的区别:React 钩子在每个render函数上运行,但是 Vue的setup 只在初始化时运行一次

Vue 设置监听器(生命周期和响应值),而 React 指定每个render的效果。

事件处理

Vue 和 React 的事件处理是不同语言方式的另一个体现。React 没有特殊的语法;它只是 JavaScript 函数。Vue 提供了侦听和发出事件的语法。

// MyVueComponent
<button @click="$emit('increment')">Increment</button>
<MyVueComponent @increment="methodName" />

// MyReactComponent
<button onClick={props.onIncrement}>Increment</button>
<MyReactComponent onIncrement={jsFunction} />

这里看到不同的处理事件的方式。React 向组件传递一个 JavaScript 函数。Vue 组件发出事件,这些事件被标识为带有关联数据的字符串。

静态分析

在某些方面,React 更适合静态分析。例如 TypeScript,React 以 javascript 为中心的语言方式使它更接近 TypeScript 语言,所以大多数编辑器/工具都能较好的配合。

一些 Vue 特性,如命名插槽、事件和它们的 props(相当于 React 子元素),对于完整的静态分析来说太动态了。例如,组件可以发出自定义事件,但没有明显的方法写出这种合约。

Vue 提供了一个全局命名空间,但不总是推荐这样做。可以通过名称向全局命名空间注册组件。Vue 插件可以注入全局方法、属性和 mixins。全局名称空间有时很方便,但在使用工具和可伸缩代码库时效果不太好。

更新模型

Vue 和 React 在功能上最大的区别是它们如何处理数据的更新。Vue 使用 observable(通过 JavaScript 的proxies或者defineProperty)来完成数据的响应。简单来说,它修改数据以跟踪何时读取或写入属性。这允许细粒度的依赖跟踪;Vue 知道哪些属性已经被读取,因此只有当这些属性发生变化时,它才会重新呈现和更新视图。这比React.memo更明智一些。

相比较,React 使用一种主动更新的模式,渲染通常被函数调用(状态更新或 reducer 分配时)触发,当 React 组件更新时,它也会重新渲染其所有子代。

// MyVueComponent
<button @click="count += 1">{{ count }}</button>
Vue.extend({
  data: {
    count: 0
  }
})

// React Component
function MyReactComponent() {
  const [count, setCount] = React.useState(0);
  return <button onClick={() => setCount(count => count + 1)}>{count}</button>;
}

Vue 的更新模型就好像所有组件都包装在React.memo中一样,相同的是其函数只动态的比较最后渲染时使用的 props/状态。

Vue 的更新模型有点像 mobx。Vue 的计算属性功能比较好,每当计算属性的数据发生更改时,Vue 都会重新渲染当前页面,即使计算属性本身未更改也会如此。在 React 中如果不创建包裹组件,就很难使用React.useMemo来这样表达。

开箱即用,Vue 执行更细粒度的更新,因此默认情况下,Vue 更新的性能更高。当然,React 拥有React.memo但是需要理解闭包以及什么时候使用React.useMemo和React.useCallback。但 Vue 并没有摆脱困境,通过 注入 observable 来驱动更新是有陷阱的。

API

React 的 API 更小,需要学习的特定于 React 的概念更少(忽略 concurrent 模式和时间切片)。

但在 Vue 中有更多方便之处:

v-model

v-model 支持数据双向绑定:

// MyVueComponent
;<div>
  <input v-model='message' />
  <p>{{ message }}</p>
</div>
Vue.extend({
  data: {
    message: '',
  },
})

React 文档中表示:在 React 中,数据是单向流动的:从所有者到子节点。我们认为这使你的应用程序的代码更容易理解。您可以将其视为“单向数据绑定”。

function MyReactComponent() {
  const [message, setMessage] = React.useState('');
  return (
    <div>
      <input value={message} onChange={e => setMessage(e.target.value} />} />
      <p>{message}</p>
    </div>
  );
}

类名绑定

Vue 具有特殊的类和样式处理。这些属性会被合并,还会处理成对象映射和数组。

// MyVueComponent
<div :class="my-class-name">Hello</div>
<MyVueComponent :class="{ active: isActive }" />

但在 React 中,类名绑定没有什么特别之处,许多人会引入第三方库来处理样式(比如 classnames、CSS in JS)

function MyReactComponent({ className }) {
  return <div className={'my-class-name ' + className}>Hello</div>
}
;<MyReactComponent className={isActive ? 'active' : ''} />

Vue 作为一个框架

React 标榜自己是一个库(library),而 Vue 是一个框架(framework)。这个界线很模糊,但是 Vue 比 React 有更多的开箱即用(out-of-the-box)的功能:Vue 有内置的过渡和动画,拥有用于路由和状态管理(vuex)的库。

React 核心,只关注渲染层。其他部分由生态系统提供,且其生态系统非常活跃。

相同点

Vue 和 React 有诸多不同,但是也有一些相似点。它们都是用于构建 web UI 视图的库并且很多概念都能从一个映射到另一个。

  • 两者都使用虚拟 DOM 并支持 JSX
  • Vue 插槽和 React 子节点
  • Vue 的 props/state 和 React 的 props/state
  • Vue 的 teleport 和 React 的 portal

你应该使用哪个

首先,无论用哪个你都能获得成功和成效。(此外,据大佬反馈,Vue3.0 解决了 Vue 2.x 的很多痛点。)

如果你比较钟爱类型系统,那么更推荐使用 React,它与 TypeScript 一起工作得更好,并且拥有更纯粹的语言方法。

如果你喜欢从 HTML/静态内容开始,然后稍微使用一些 JavaScript,那么 Vue 的模板方法会比较合适。

对于不太熟悉 JavaScript 的开发人员来说,Vue 可能更容易上手(文档也很友好)。模板是直观的,可以逐步采用。不需要考虑重新呈现,数据绑定很容易理解。但这并不代表不能用 Vue 构建复杂的应用程序。如果你在 JavaScript 上花了很多时间,您可能会喜欢 React 更纯粹的语言方法。

最后,我们很难忽视 React 的大规模应用和庞大的生态系统。对公司来说,React 将是风险较小的选择。拥有 React 经验多于拥有 Vue 经验的工程师在招聘上可能会更容易。此外,还有更多可供选择的 React 渲染目标,比如 React Native,您可能会发现它们很有用。

你也可以使用这两个框架来提高效率。

vuejs
58 views
Comments
登录后评论
Sign In