1. 前言
本文将以 React 和 Vue3 进行同步对比,带大家快速掌握 React。这个系列分为上下两篇,上篇内容包括:
- 组件
- JSX
- 插值
- 数据通信
- 渲染
- 事件
- 状态
下篇包括:
- 元素引用
- 跨级传值
- Portals
- Suspense
- Error Boundaries
- Hooks
2. 组件
第一次遇见"组件"是比较抽象的,实际上,它相当于电路板上的电阻、电容、变压器、二极管等等元器件,这些元器件共同组成了一块电路板。
同理,网页中的一个个UI块就是一个个元器件,它们被称为"组件",这些组件共同构成了一张完整的UI界面。
Vue:
html
<MyHeader />
<MyMain />
<MyFooter />
React:
html
<MyHeader />
<MyMain />
<MyFooter />
3. JSX
组件的本质是 JS 函数,以 MyHeader 组件为例:
Vue:
ts
// MyHeader.ts
export default {
template: '<div>MyHeader</div>',
};
// SFC
// MyHeader.vue
<template>
<div>MyHeader</div>
</template>
React:
ts
// MyHeader.tsx
export default function MyHeader() {
return <div>MyHeader</div>;
}
在 React 中返回了一串 HTML 标记,这种语法被称为 JSX,它等价于:
tsx
React.createElement('div', null, 'MyHeader');
注意:Vue 中也支持 JSX 语法(搭配插件:@vitejs/plugin-vue-jsx
):
tsx
// MyHeader.tsx
import { defineComponent } from 'vue';
export const MyHeader = defineComponent({
setup() {
return () => <div>MyHeader</div>;
},
});
4. 插值
在Vue中插值使用一对双大括号表示,而在React中使用一对大括号。
Vue:
tsx
<h1>Hello, {{ msg }}.</h1>
React:
tsx
<h1>Hello, {msg}.</h1>
5. 数据通信
数据的通信分为传值和传组件,都是从外部传入。
5.1 传值
通过自定义属性进行传值。
Vue:
tsx
// 父组件
<Coding who="me" />
<Coding who="you" />
<Coding who="them" />
// Coding.vue
<script setup>
defineProps(['who']);
</script>
<template>
<div>Coding for {{ who }}.</div>
</template>
React:
tsx
// 父组件
<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:
tsx
// 父组件
<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:
tsx
// 父组件
<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:
tsx
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:
tsx
<ul>
{list.map((item) => (
<li key={item.id}>
{item.name}-{item.price}
</li>
))}
</ul>
6.2 条件渲染
Vue:
tsx
const visible = false;
<p v-if="visible">显示</p>
<p v-else>隐藏</p>
React:
tsx
const visible = false;
{visible ? <p>显示</p> : <p>隐藏</p>}
7. 事件
在网页中可以实现很多交互功能,借助于各种事件:点击事件、鼠标移动事件、键盘点击事件......
Vue:
tsx
<form
@submit="
(e) => {
e.preventDefault();
console.log('提交了');
}
"
>
<input @change="(e) => console.log('内容变化了:', e.target.value)" />
<button @click="() => console.log('点我了')">点我提交</button>
</form>
React:
tsx
<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:
tsx
import { ref } from 'vue';
const count = ref(0);
<p>
{{ count }}
<button @click="() => count++">+1</button>
</p>
React:
tsx
import { useState } from 'react';
const [count, setCount] = useState(0);
<p>
{count}
<button onClick={() => setCount(count + 1)}>+1</button>
</p>
- 用户点击按钮,触发 setCount
- 更新状态 count
- {count} 读取新状态
技术交流:
- 公众号:见嘉 Being Dev
- v:with_his_x