1.模板语法
1-1.JSX
function App() {
return (
<div>
<h1>Hello, World!</h1>
<p>This is a simple JSX example.</p>
</div>
);
}
1-2.模板插值
function App() {
return (
<div>
<h1>Hello, {name}!</h1>
<p>{isLoggedIn ? <p>欢迎回来</p> : <p>请登录</p>}</p>
</div>
);
}
1-3.属性绑定
<img src={avatarUrl} alt="头像" />
2.组件系统
2-1.函数式组件
import React, { useState, useEffect } from 'react';
function FunctionalCounter() {
// 使用 useState Hook 管理状态
const [count, setCount] = useState(0);
const [message, setMessage] = useState('');
// 使用 useEffect Hook 处理副作用
useEffect(() => {
document.title = `点击了 ${count} 次`;
if (count > 5) {
setMessage('点击次数已经超过5次了!');
} else {
setMessage('');
}
}, [count]); // 仅在 count 变化时执行
// 事件处理函数
const handleIncrement = () => {
setCount(prevCount => prevCount + 1);
};
const handleReset = () => {
setCount(0);
};
return (
<div>
<h2>函数式组件计数器</h2>
<p>当前计数: {count}</p>
<p style="color: 'red'">{message}</p>
<button onClick={handleIncrement}>增加</button>
<button onClick={handleReset}>重置</button>
</div>
);
}
export default FunctionalCounter;
2-2.类组件
import React, { Component } from 'react';
class ClassCounter extends Component {
// 构造函数初始化状态
constructor(props) {
super(props);
this.state = {
count: 0,
message: ''
};
// 绑定方法
this.handleIncrement = this.handleIncrement.bind(this);
this.handleReset = this.handleReset.bind(this);
}
// 生命周期方法
componentDidMount() {
document.title = `点击了 ${this.state.count} 次`;
}
componentDidUpdate() {
document.title = `点击了 ${this.state.count} 次`;
if (this.state.count > 5 && !this.state.message) {
this.setState({ message: '点击次数已经超过5次了!' });
} else if (this.state.count <= 5 && this.state.message) {
this.setState({ message: '' });
}
}
// 类方法
handleIncrement() {
this.setState(prevState => ({
count: prevState.count + 1
}));
}
handleReset() {
this.setState({ count: 0 });
}
render() {
return (
<div>
<h2>Class 组件计数器</h2>
<p>当前计数: {this.state.count}</p>
<p style="color: 'red'">{message}</p>
<button onClick={this.handleIncrement}>增加</button>
<button onClick={this.handleReset}>重置</button>
</div>
);
}
}
export default ClassCounter;
3.生命周期
React 函数式组件 (Hooks) | Vue 3 组合式 API | 说明 |
---|---|---|
useState + useEffect | setup() + ref() | 组件初始化阶段 |
useEffect(() => {}, []) | onMounted() | 组件挂载完成后执行(相当于 componentDidMount) |
useEffect(() => { return () => {} }, []) | onUnmounted() | 组件卸载时执行清理(相当于 componentWillUnmount) |
useEffect(() => {}, [dep]) | onUpdated() / watch | 依赖项变化时执行(相当于 componentDidUpdate) |
useMemo/useCallback | computed/watch | 性能优化,避免不必要的计算/渲染 |
4.Props
React props
是一个对象,包含了组件接收的所有属性。
- 父组件可以传递任意类型的数据:字符串、数字、布尔值、对象、函数、
JSX
等。 - 子组件通过参数或
props
对象访问这些数据。
// 父组件
function App() {
return <Welcome name="Alice" />;
}
// 子组件
function Welcome(props) {
return <h1>Hello, {props.name}!</h1>;
}
而在 react
中,父子通信的设计,相对来说比 Vue
直接利用 props
传递参数即可:
// 父组件
function App() {
const handleClick = () => {
console.log('React Button clicked')
}
return <Button onClick={handleClick} />
}
// 子组件
function Button({ onClick }) {
return <button onClick={onClick}>Click me</button>
}
5.Events
React
事件是对浏览器原生事件的封装。
React
使用的是一个叫做**合成事件(SyntheticEvent)**的系统,它封装了原生 DOM
事件,为了实现更好的跨浏览器兼容性和性能。
譬如 React
中使用的是 on
前缀来绑定事件,而不是 Vue
中的 v-on
。
function MyButton() {
return (
<button onClick={() => alert('Button clicked!')}>
Click me
</button>
)
}
6.Refs
ref
是 React
提供的一个特殊属性,用来获取某个组件或 DOM
节点的引用。
常用于需要直接操作 DOM
,或者调用子组件的实例方法(class
组件)时。
// 函数式组件
import React from 'react'
function MyComponent() {
const inputRef = React.useRef(null) // 创建 ref
const focusInput = () => {
inputRef.current.focus() // 通过 ref 访问 DOM 节点
}
return (
<>
<input ref={inputRef} type="text" />
<button onClick={focusInput}>聚焦输入框</button>
</>
)
}
// 类组件
class MyComponent extends React.Component {
constructor(props) {
super(props)
this.inputRef = React.createRef()
}
focusInput = () => {
this.inputRef.current.focus()
}
render() {
return (
<>
<input ref={this.inputRef} type="text" />
<button onClick={this.focusInput}>聚焦输入框</button>
</>
)
}
}
7.Slots
在 Vue
中,slots
是一种允许父组件向子组件传递内容的机制。分为默认插槽和具名插槽。
而在 React
中可分别用 props.children
和自定义props来实现这个功能:
function Layout({ header, footer, children }) {
return (
<div>
<header>{header}</header>
<main>{children}</main>
<footer>{footer}</footer>
</div>
)
}
function App() {
return (
<Layout
header={<h1>这是头部</h1>}
footer={<small>这是尾部</small>}
>
<p>这里是主体内容</p>
</Layout>
)
}
8.性能优化
8-1.React.memo
React.memo
是一个高阶组件,用于优化组件的渲染性能。
它可以缓存组件的渲染结果,避免不必要的重新渲染,只有当 props 改变时才重新渲染。
import React from 'react';
function MyComponent(props) {
return <div>{props.value}</div>;
}
export default React.memo(MyComponent);
TIP
Vue
中可以看做 v-once
、defineComponent
+ shallowRef
+ watchEffect
等。
8-2.useMemo
useMemo
是一个 Hook,用于缓存计算结果,避免在每次渲染时都重新计算。
import React, { useMemo } from 'react';
function MyComponent(props) {
const computedValue = useMemo(() => {
return expensiveCalculation(props.value);
}, [props.value]); // 仅在 props.value 改变时重新计算
return <div>{computedValue}</div>;
}
function expensiveCalculation(value) {
// 模拟一个耗时的计算
let result = 0;
for (let i = 0; i < 1000000; i++) {
result += value;
}
return result;
}
TIP
Vue
中可以看做 computed
。
8-3.useCallback
useCallback
是一个 Hook
,用于缓存函数实例,避免在每次渲染时都创建新的函数。
import React, { useCallback } from 'react';
function MyComponent({ onClick }) {
const handleClick = useCallback(() => {
onClick();
}, [onClick]); // 仅在 onClick 改变时重新创建函数
return <button onClick={handleClick}>点击我</button>;
}
TIP
Vue
通常不需要 useCallback
类似的功能,因为:
方法写在
methods
或setup
里本来就只创建一次。Vue
子组件不会因为传入的方法地址变化就重新渲染(不是纯函数式组件)。
8-4.组件懒加载
React
支持懒加载组件,可以使用 React.lazy
和 Suspense
来实现。
import React, { Suspense } from 'react';
const LazyComponent = React.lazy(() => import('./LazyComponent'));
export default function App() {
return (
<Suspense fallback={<div>Loading...</div>}>
<LazyComponent />
</Suspense>
);
}
TIP
Vue
中可以使用 defineAsyncComponent
来实现类似的功能。
import { defineAsyncComponent } from 'vue';
export default {
components: {
AsyncComponent: defineAsyncComponent(() => import('./AsyncComponent.vue'))
}
}
<template>
<Suspense>
<template #default>
<AsyncComponent />
</template>
<template #fallback>
<div>加载中...</div>
</template>
</Suspense>
</template>