V

Vue.js 开发人员的 React 指南

2025-06-07

Vue.js 开发人员的 React 指南

如果你已经学过一门语言或框架,学习类似的会更容易。你不用从头到尾阅读文档,只需思考“如何用 Y 实现 X?”。

在本文中,我向想要学习 React 的 Vue.js 开发人员介绍了使用 React 实现 Vue.js 功能的方式。

(我不鼓励任何人从 Vue.js 切换到 React!了解两者会更好,也更有趣,对吧?)

成分

如何创建组件?

Vue.js 方式

Vue 组件由 3 个块组成—— 、、<template>并且该文件应该具有扩展名。<script><style>.vue

<template>
  <div>
    <h1>Sample</h1>
    <h2>This is a component.</h2>
  </div>
</template>

<script>
export default {
  // data and behaviors.
}
</script>

<style>
/* how this component looks */
</style>
Enter fullscreen mode Exit fullscreen mode

反应方式

在 React 中,有两种创建组件的方法——函数和类。

下面是创建组件的功能方式的示例。

import React from 'react';

function Sample() {
  return (
    <div>
      <h1>Sample</h1>
      <h2>This is a component.</h2>
    </div>
  );
}

export default Sample;
Enter fullscreen mode Exit fullscreen mode

函数式组件是一个返回 React 元素的函数。它看起来像 JavaScript 返回 HTML,但实际上不是。它是JSX

为了使用 JSX,你必须导入 React,尽管它似乎没有被直接引用。(不过在 React v17.0 中,你可以选择不导入 React,而只是为了使用 JSX。详情请阅读这篇官方文章。)

下面是使用类语法创建反应组件的另一种方法。

import React from 'react';

class Sample extends React.Component {
  render() {
    return (
      <div>
        <h1>Sample</h1>
        <h2>This is a component.</h2>
      </div>
    );
  }
}

export default Sample;
Enter fullscreen mode Exit fullscreen mode

类组件的render方法返回 React 元素。

那么,两者之间有什么区别,您应该选择哪种方式来编写自己的 React 组件?

在 v16.7 及以下版本中,类组件具有状态管理(data在 Vue.js 中)和生命周期方法——这两者对于有用的组件都至关重要——而功能组件则没有。

但是,从 v16.8 开始,React 在函数组件中引入了Hooks。Hooks负责状态管理和“副作用”(渲染后应该执行的操作)。

尽管一些生命周期方法在钩子中没有被“翻译”,但函数式组件可以完成与类组件几乎相同的功能。React 团队推荐你首选函数式组件。

当你准备好后,我们鼓励你在新编写的组件中尝试使用 Hooks。
从长远来看,我们预计 Hooks 将成为人们编写 React 组件的主要方式。
我应该使用 Hooks、类,还是两者兼而有之?

所以,如果你开始一个全新的 React 项目,或者你是 React 新手,我认为你应该首先考虑用函数式编写。如果你想使用只有类才能实现的功能,那么就引入类组件。函数式组件和类组件共存是完全没问题的。

在本文中,我将解释函数式方法。

模板

Vue.js 方式

Vue 组件有自己的语法<template>例如v-bind,,v-forv-if

<template>
  <div>
    <h1>Hello, {{ name }} !</h1>
    <a :href="link">Click me</a>
    <ul>
      <li v-for="item in items" :key="item.key">
        {{ item.title }}
      </li>
    </ul>
    <p v-if="isActive">Paragraph</p>
    <p v-show="isShow">Second paragraph</p>
  </div>
</template>
Enter fullscreen mode Exit fullscreen mode

反应方式

在 React 中,您可以使用 JSX。

return (
  <div>
    <h1>Hello, {name} !</h1>
    <a href={link}>Click me</a>
    <ul>
      {items.map(item => (
        <li key={item.key}>{item.title}</li>
      ))}
    </ul>
    {isActive && <p>Paragraph</p>}
    <p style={{ display: isShow ? 'initial' : 'none' }}>Second paragraph</p>
  </div>
);
Enter fullscreen mode Exit fullscreen mode
  • JSX 不是模板引擎。它只有一个特殊语法 -- {},其余的都只是 JavaScript。
  • 里面的语句{}被评估为 JavaScript。
  • 没有等效的v-show。因此基本上您应该手动操作display样式属性。
  • 我稍后会讨论 CSS 类。

和 Vue 的 一样<template>,函数式组件必须只返回一个根元素。但 React 有一个方便的辅助组件<React.Fragment>,它允许你返回多个元素,这样你就不用<div>为了满足框架的要求而用无用元素包裹它们了。

return (
  <React.Fragment>
    <h1>...</h1>
    <h2>...</h2>
    <h3>...</h3>
  </React.Fragment>
);
Enter fullscreen mode Exit fullscreen mode

<React.Fragment>不会渲染为 DOM。在上面的例子中,你只会得到<h1><h2>和。<h3>

而且,<React.Fragment>它有语法糖。它的名称可以省略。也就是说,上面的代码片段可以写成下面这样。

return (
  <>
    <h1>...</h1>
    <h2>...</h2>
    <h3>...</h3>
  </>
);
Enter fullscreen mode Exit fullscreen mode

很奇怪但是很方便,不是吗?

CSS 类

Vue.js 方式

Vue.js 提供了v-bind:class一种操作 HTML 属性的方法class

<button class="btn" :class="{ 'btn-primary': isPrimary }">...</button>
<button class="btn" :class="['btn-primary', 'btn-small']">...</button>
Enter fullscreen mode Exit fullscreen mode

反应方式

React 中没有特殊的方法。className只是属性的等价物classclass是 JavaScript 中的保留关键字之一,因此 JSX 调用 this className

return <button className="btn btn-primary">...</button>;
Enter fullscreen mode Exit fullscreen mode

尽管如此,classnames库将帮助您处理 HTML 类。

import classNames from 'classnames';
Enter fullscreen mode Exit fullscreen mode

就像v-bind:class

const buttonClass = classNames({
  btn: true,
  'btn-primary': isPrimary
});

return <button className={buttonClass}>...</button>;
Enter fullscreen mode Exit fullscreen mode

HTML

Vue.js 方式

要注入 HTML 字符串,您可以v-html在 Vue.js 中使用。

<div v-html="htmlString"></div>
Enter fullscreen mode Exit fullscreen mode

反应方式

在 React 中,有一个名为 的 prop dangerouslySetInnerHTML。它实际上警告你随意插入 HTML 字符串是危险的举动。dangerouslySetInnerHTML它接受一个具有__html以 HTML 字符串作为值的属性的对象。

return <div dangerouslySetInnerHTML={{ __html: htmlString }} />;
Enter fullscreen mode Exit fullscreen mode

活动

Vue.js 方式

@在 Vue.js 中,事件用语法(语法糖 for )来表示v-on

<button @click="handleClick">Click me</button>

<form @submit.prevent="handleSubmit">...</form>
Enter fullscreen mode Exit fullscreen mode

反应方式

React 采用更类似HTML 的方式。事件处理程序被传递给名为 onEventName 的 prop——例如onChangeonSubmit

const handleClick = e => {/* blah blah... */};

return <button onClick={handleClick}>Click me</button>;
Enter fullscreen mode Exit fullscreen mode

没有类似的事件修饰符.prevent

州(数据)

Vue.js 方式

在 Vue.js 中,组件的内部状态由方法的返回值定义data

<script>
export default {
  data() {
    return {
      count: 0
    }
  }
}
</script>
Enter fullscreen mode Exit fullscreen mode

在组件的其他部分内部,您可以通过引用其状态值this

methods: {
  increment() {
    this.count += 1;
  }
}
Enter fullscreen mode Exit fullscreen mode

反应方式

在 React 中,你可以使用useState钩子。嘿,钩子来了!

import React, { useState } from 'react'

function Counter() {
  const [count, setCount] = useState(0);

  const handleClick = () => setCount(count + 1);

  return <button onClick="handleClick">{count}</button>;
}
Enter fullscreen mode Exit fullscreen mode

Hooks 是用于访问 React 魔法的函数。useState是用于管理组件状态的函数。

useState以状态的默认值作为参数,返回一个包含 0. “状态变量” 和 1. “更新状态的函数” 的数组。状态的值只能通过该函数进行更新。

useState由各州发起呼叫。

const [name, setName] = useState("John Doe");
const [age, setAge] = useState(20);
Enter fullscreen mode Exit fullscreen mode

您可以将对象设置为状态的值。

const [user, setUser] = useState({ name: "John Doe", age: 20 });
Enter fullscreen mode Exit fullscreen mode

表格

Vue.js 方式

在 Vue.js 中,v-model处理表单输入。

<input type="text" v-model="name" />
Enter fullscreen mode Exit fullscreen mode

v-model让您实现双向数据流。

反应方式

React 没有引入双向数据更新的语法糖,需要自行结合 state 和 event 来实现。

const [name, setName] = useState('');
const handleInput = e => setName(e.target.value);

return <input type="text" onChange="handleInput" value="name" />;
Enter fullscreen mode Exit fullscreen mode

几乎每次处理表单时都要写这种样板代码,确实有点烦人。但我觉得这种简洁,或者说“不加糖”、“尽可能自己写你需要的东西”的风格很符合 React 的风格。

方法

Vue.js 方式

在 中定义的方法内部methods,您可以引用状态(data)。并且可以在模板内部引用这些方法。

<script>
export default {
  methods: {
    sayHello() {
      console.log(`Hello, ${this.name}!`)
    }
  }
}
</script>
Enter fullscreen mode Exit fullscreen mode

反应方式

React 中没有类似 Vue 的功能methods。React 组件本质上只是一个 JavaScript 函数,所以你可以直接使用它。

function MyComponent() {
  const [name, setName] = useState('John');

  function sayHello() {
    console.log(`Hello, ${name}!`);
  }

  return <button onClick={sayHello}>...</button>;
}
Enter fullscreen mode Exit fullscreen mode

参考

Vue.js 方式

在 Vue.js 中,ref您可以直接访问 DOM。

<template>
  <div>
    <div ref="foo">...</div>
    <button @click="handleClick">Click me</button>
  </div>
</template>

<script>
export default {
  methods: {
    handleClick() {
      console.log(this.$refs.foo);
    }
  }
}
</script>
Enter fullscreen mode Exit fullscreen mode

反应方式

React 具有与 Vue 类似的功能ref

使用useRefhook,你可以创建一个用于访问 DOM 的“ref 对象”。该对象的current属性包含对 DOM 的引用。

import React, { useRef } from 'react';

function MyComponent() {
  const target = useRef(null);

  const handleClick = () => {
    console.log(target.current);
  };

  return (
    <>
      <div ref={target}>...</div>
      <button onClick={handleClick}>Click me</button>
    </>
  );
}

export default MyComponent;
Enter fullscreen mode Exit fullscreen mode

计算属性

Vue.js 方式

Vue.js 具有“计算属性”。

<p>Hello, {{ fullName }} !</p>
Enter fullscreen mode Exit fullscreen mode
export default {
  data() {
    return {
      firstName: 'John',
      lastName: 'Doe'
    };
  },
  computed: {
    fullName() {
      return `${this.firstName} ${this.lastName}`;
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

计算属性是捕获计算结果的函数,其行为类似于模板块中的属性。

反应方式

我认为useMemohook 是“计算属性”的 React 版本。

import React, { useMemo } from 'react';

function MyComponent() {
  const [firstName, setFirstName] = useState("John");
  const [lastName, setlastName] = useState("Doe");

  const fullName = useMemo(() => {
    return `${firstName} ${lastName}`;
  }, [firstName, lastName]);

  return <p>Hello, {fullName} !</p>;
}
Enter fullscreen mode Exit fullscreen mode

useMemo将函数作为第一个参数,将数组作为第二个参数,并返回记忆值。

  • 每次更新 props 或状态时,React 的功能组件都会重新渲染。
  • useMemo但是,仅当作为第二个参数传递的数组中的值被更新时,才会重新计算第一个参数的函数。
  • 如果第二个参数数组中的值未更新,则将返回缓存值。

这种行为类似于 Vue 的计算属性,但它与其说是一种常见的模式,不如说是一种计算属性。你应该useMemo只在真正需要优化时才使用它(我从这篇文章中学到的)。

手表

Vue.js 方式

Vue.js 为您提供了观察者——“对数据变化做出反应的更通用的方式”。

export default {
  watch: {
    name(valueAfterUpdate, valueBeforeUpdate) {
      // ...
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

反应方式

React 没有与观察者相对应的东西。

你可以使用钩子来实现类似的功能useEffect。我将在下一节中向你展示这个钩子。

但我经常认为该选项的用例并不多watch,因为大多数时候,它可以用变化事件代替。

生命周期

Vue.js 方式

Vue.js 有许多生命周期钩子。

export default {
  created() {/* ... */},
  mounted() {/* ... */},
  updated() {/* ... */},
  destroyed() {/* ... */}
}
Enter fullscreen mode Exit fullscreen mode

反应方式

在 React 函数式组件中,没有生命周期的概念。这里要简单得多。

  • 当其 props 或状态更新时,功能组件会被渲染并重新渲染。
  • 如果您想在渲染后立即执行某项操作,请将该操作放在useEffect钩子中。
import React, { useState, useEffect } from 'react';

function MyComponent() {
  const [items, setItems] = useState([]);

  useEffect(() => {
    someApi.getItems().then(response => {
      setItems(response.data);
    });
  }, []);
Enter fullscreen mode Exit fullscreen mode

useEffect根据作为第二个参数传递的内容,行为会有所不同。

// if there is no 2nd argument,
// 1st argument is called on every renders.
useEffect(() => {});

// if 2nd argument is an empty array,
// 1st argument is called only on first render.
useEffect(() => {}, []);
// this is like "mounted" in Vue.js

// if 2nd argument contains one or more items,
// 1st argument is called on first render and when the items are updated.
useEffect(() => {}, [aaa, bbb]);
// this is like "mounted" plus "updated" & "watch", I guess.
Enter fullscreen mode Exit fullscreen mode

useEffect的第一个参数可以返回“清理”函数,该函数在其组件从 DOM 中删除之前调用。

import React, { useEffect } from 'react';

function MyComponent() {
  useEffect(() => {
    // ...

    return () => {
      // clean up function.
      // this is like "destroyed" in Vue.
    };
  }, []);

  return <div>...</div>;
}
Enter fullscreen mode Exit fullscreen mode

另一方面,类组件具有constructor与 Vue.js 类似的生命周期方法。我不会在本文中向您展示这些内容,但您可以从这篇文章中了解它们。

组件之间的交互

道具

Vue.js 方式

props选项用于将数据从父组件传递到其子组件。

<Child :name="test" :item="sampleData" />
Enter fullscreen mode Exit fullscreen mode
<script>
function Item(one, two) {
  this.one = one
  this.two = two
}

export default {
  // validate its value with "type" and "required".
  props: {
    name: {
      type: String,
      required: false,
      default: 'John Doe'
    },
    item: {
      type: Item,
      required: true
    }
  }
}
</script>
Enter fullscreen mode Exit fullscreen mode

反应方式

在 React 中,从父级传递给子级的属性/特性也称为props

<Child name={test} item={sampleData} />
Enter fullscreen mode Exit fullscreen mode

功能组件的第一个参数是 props。

import React from 'react';

function Child(props) {
  // props.name
  // props.item
}
Enter fullscreen mode Exit fullscreen mode

您可以使用prop-types库进行验证。

import React from 'react';
import PropTypes from 'prop-types';

function Child(props) {
  // props.name
  // props.item
}

Child.propTypes = {
  name: PropTypes.string,
  item: PropTypes.shape({
    one: PropTypes.string.isRequired,
    two: PropTypes.number.isRequired
  }).isRequired
};

Child.defaultProps = {
  name: 'John Doe'
};

export default Child
Enter fullscreen mode Exit fullscreen mode

发出事件

Vue.js 方式

在 Vue.js 中,子组件通过$emit方法将事件通知给其父组件。

onSomethingHappened() {
  this.$emit('hello');
}
Enter fullscreen mode Exit fullscreen mode

然后,使用语法为通知事件注册一个处理程序@

<Child @hello="parentMethod" />
Enter fullscreen mode Exit fullscreen mode

反应方式

React 没有事件触发的语法。你只需要将处理函数作为 prop 传递即可——也就是说,父组件决定要做什么,然后子组件执行。

function Child({ onHello }) {
  const handleClick = () => {
    console.log('hello there');
    onHello();
  };

  return <button onClick={handleClick}>click me</button>;
}
Enter fullscreen mode Exit fullscreen mode
function Parent() {
  const parentMethod = () => {/* blah blah... */};

  return <Child onHello={parentMethod} />;
}
Enter fullscreen mode Exit fullscreen mode

投币口

Vue.js 方式

Vue.js 有slot插入子元素的功能。

<Content>
  <p>Hello world</p>
</Content>
Enter fullscreen mode Exit fullscreen mode

Content组件如下:

<template>
  <article>
    <h1>This is a title.</h1>
    <slot></slot>
  </article>
</template>
Enter fullscreen mode Exit fullscreen mode

当您要插入多个块时,您可以为每个块命名。

<MyComponent>
  <template #header>
    <MyHeader />
  </template>
  <template #content>
    <MyContent />
  </template>
  <template #footer>
    <MyFooter />
  </template>
</MyComponent>
Enter fullscreen mode Exit fullscreen mode

反应方式

在 React 中,childrenprop 有插入元素。

<Content>
  <p>Hello world</p>
</Content>
Enter fullscreen mode Exit fullscreen mode
function Content({ children }) {
  // children -> <p>Hello world</p>
  return (
    <article>
      <h1>This is a title.</h1>
      {children}
    </article>
  );
}
Enter fullscreen mode Exit fullscreen mode

您既不能拥有多个children,也不能命名它。

children只是一个道具。上面的例子本质上与下面相同:

<Content children={<p>Hello world</p>} />
Enter fullscreen mode Exit fullscreen mode

因此您只需这样做即可插入多个元素。

return (
  <MyComponent
    header={<MyHeader />}
    content={<MyContent />}
    footer={<MyFooter />}
  />
);
Enter fullscreen mode Exit fullscreen mode
function MyComponent({ header, content, footer }) {
  return (
    <div>
      <header>{header}</header>
      <main>{content}</main>
      <footer>{footer}</footer>
    </div>
  )
}
Enter fullscreen mode Exit fullscreen mode

总结

以下是我的印象:

  • React 比 Vue.js 简单得多,并且有更多的空间供您即兴发挥。
  • Vue.js 拥有更多 API,但更易于学习。

从这个意义上来说,我认为 Vue.js 设计得很好。我特别推荐给 JS 框架新手。这也是我第一个成功学习的 JS 框架(之前学习过 angular.js,但失败了)。

但是,现在我更喜欢 React。它简单而且足够用。

您更喜欢哪一个?

好了,就到这里啦!感谢阅读。希望你喜欢,并且这对你的学习有帮助!

文章来源:https://dev.to/_masahiro_h_/vue-js-developers-guide-to-react-lg0
PREV
Kubernetes 简介
NEXT
如何使用 yup 和 formik 构建一个带有验证的简单表单(适合初学者)这篇文章将分为 3 个部分该表单的最终代码将是恭喜,您刚刚完成了这个简单的教程。