likes
comments
collection
share

了解了这些你就掌握了 React(上)

作者站长头像
站长
· 阅读数 3

1. 前言

本文将以 React 和 Vue3 进行同步对比,带大家快速掌握 React。这个系列分为上下两篇,上篇内容包括:

  • 组件
  • JSX
  • 插值
  • 数据通信
  • 渲染
  • 事件
  • 状态

下篇包括:

  • 元素引用
  • 跨级传值
  • Portals
  • Suspense
  • Error Boundaries
  • Hooks

2. 组件

第一次遇见“组件”是比较抽象的,实际上,它相当于电路板上的电阻、电容、变压器、二极管等等元器件,这些元器件共同组成了一块电路板。

了解了这些你就掌握了 React(上)

同理,网页中的一个个UI块就是一个个元器件,它们被称为“组件”,这些组件共同构成了一张完整的UI界面。

了解了这些你就掌握了 React(上)

Vue:

<MyHeader />
<MyMain />
<MyFooter />

React:

<MyHeader />
<MyMain />
<MyFooter />

3. JSX

组件的本质是 JS 函数,以 MyHeader 组件为例:

Vue:

// MyHeader.ts
export default {
  template: '<div>MyHeader</div>',
};

// SFC
// MyHeader.vue
<template>
  <div>MyHeader</div>
</template>

React:

// MyHeader.tsx
export default function MyHeader() {
  return <div>MyHeader</div>;
}

在 React 中返回了一串 HTML 标记,这种语法被称为 JSX,它等价于:

React.createElement('div', null, 'MyHeader');

注意:Vue 中也支持 JSX 语法(搭配插件:@vitejs/plugin-vue-jsx):

// MyHeader.tsx
import { defineComponent } from 'vue';

export const MyHeader = defineComponent({
  setup() {
    return () => <div>MyHeader</div>;
  },
});

4. 插值

在Vue中插值使用一对双大括号表示,而在React中使用一对大括号。

Vue:

<h1>Hello, {{ msg }}.</h1>

React:

<h1>Hello, {msg}.</h1>

5. 数据通信

数据的通信分为传值和传组件,都是从外部传入。

5.1 传值

通过自定义属性进行传值。

Vue:

// 父组件
<Coding who="me" />
<Coding who="you" />
<Coding who="them" />

// Coding.vue
<script setup>
defineProps(['who']);
</script>

<template>
  <div>Coding for {{ who }}.</div>
</template>

React:

// 父组件
<Coding who={'me'} />
<Coding who={'you'} />
<Coding who={'them'} />

// Coding.tsx
export default function Coding(props: { who: string }) {
  return <div>Coding for {props.who}.</div>;
}

5.2 传组件

通过插槽来传组件,这就像游戏机的卡槽、电脑边上的各种接口。

Vue:

// 父组件
<MyCard>This is my card.</MyCard>
<MyCard>
  <Coding who="boss" />
</MyCard>

// MyCard.tsx
<template>
  <div :style="{ border: '1px solid #000' }">
    <slot></slot>
  </div>
</template>

React:

// 父组件
<MyCard>This is my card.</MyCard>
<MyCard>
  <Coding who={'boss'} />
</MyCard>

// MyCard.tsx
export default function MyCard({ children }: { children: React.ReactNode }) {
  return <div style={{ border: '1px solid #000' }}>{children}</div>;
}

6. 渲染

6.1 列表渲染

Vue:

const list = [
  { id: 1, name: '🍎', price: 6 },
  { id: 2, name: '🍌', price: 3 },
  { id: 3, name: '🍐', price: 5 },
];

<ul>
  <li v-for="item in list" :key="item.id">
    {{ item.name }}-{{ item.price }}
  </li>
</ul>

React:

<ul>
  {list.map((item) => (
    <li key={item.id}>
      {item.name}-{item.price}
    </li>
  ))}
</ul>

6.2 条件渲染

Vue:

const visible = false;

<p v-if="visible">显示</p>
<p v-else>隐藏</p>

React:

const visible = false;

{visible ? <p>显示</p> : <p>隐藏</p>}

7. 事件

在网页中可以实现很多交互功能,借助于各种事件:点击事件、鼠标移动事件、键盘点击事件……

Vue:

<form
  @submit="
    (e) => {
      e.preventDefault();
      console.log('提交了');
    }
  "
>
  <input @change="(e) => console.log('内容变化了:', e.target.value)" />
  <button @click="() => console.log('点我了')">点我提交</button>
</form>

React:

<form
  onSubmit={(e) => {
    e.preventDefault();
    console.log('提交了');
  }}
>
  <input onChange={(e) => console.log('内容变化了:', e.target.value)} />
  <button onClick={() => console.log('点我了')}>点我提交</button>
</form>

8. 状态

在 Vue 中使用 ref(响应式引用)、reactive(响应式对象) 方法来管理状态,而在 React 中则使用 useState 方法。

Vue:

import { ref } from 'vue';

const count = ref(0);

<p>
  {{ count }}
  <button @click="() => count++">+1</button>
</p>

React:

import { useState } from 'react';

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

<p>
  {count}
  <button onClick={() => setCount(count + 1)}>+1</button>
</p>
  1. 用户点击按钮,触发 setCount
  2. 更新状态 count
  3. {count} 读取新状态

技术交流:

  • 公众号:见嘉 Being Dev
  • v:with_his_x