一、模拟 Vue 的 watch
Vue 的 watch 用来监听数据变化并执行副作用,React 里用 useEffect 实现。
1. 基础用法(监听单个值变化)
javascript
import { useState, useEffect } from 'react';
function Demo()
{ const [count, setCount] = useState(0);
// 等价于 watch: { count(newVal, oldVal) { ... } }
useEffect(() => { console.log('count 变化了,新值:', count);
// 这里可以执行副作用,比如发请求、更新其他状态 },
[count]);
// 依赖数组里放要监听的值
return <button onClick={() => setCount(c => c + 1)}>count: {count}</button>; }
2. 立即执行(immediate: true)
Vue 中 immediate: true 会在组件初始化时就执行一次,React 里 useEffect 默认就会执行一次,无需额外配置。
3. 深度监听(deep: true)
监听对象内部属性变化时,直接放对象会导致每次渲染都触发,需要手动监听具体属性,或用 JSON 序列化
scss
const [user, setUser] = useState({ name: '张三', age: 18 });
// 监听整个对象(不推荐,会频繁触发)
useEffect(() => { console.log('user 变化了:', user); },
[JSON.stringify(user)]);
// 用 JSON.stringify 序列化对象
// 推荐:只监听具体属性
useEffect(() => { console.log('name 变化了:', user.name); }, [user.name]);
二、模拟 Vue 的 computed
Vue 的 computed 是基于依赖缓存的计算属性,React 里用 useMemo 实现。
1. 基础用法
javascript
import { useState, useMemo } from 'react';
function Demo()
{ const [count, setCount] = useState(0);
const [price, setPrice] = useState(10);
// 等价于 computed: { total() { return count * price; } }
const totalPrice = useMemo(() =>
{ console.log('计算总价'); // 只有 count 或 price 变化时才会打印
return count * price; },
[count, price]); // 依赖数组放所有用到的变量
return
( <div>
<p>数量: {count}</p>
<p>单价: {price}</p>
<p>总价: {totalPrice}</p>
<button onClick={() => setCount(c => c + 1)}>加数量</button> </div> ); }
2. 带 setter 的 computed(Vue 中 computed 可写)
React 没有直接的 setter,但可以通过自定义函数实现
javascript
import { useState, useMemo } from 'react';
function Demo(){
const [count, setCount] = useState(0);
const [price, setPrice] = useState(10);
// 只读计算属性
const totalPrice = useMemo(() => count * price, [count, price]);
// 模拟 setter,修改总价时反推数量
const setTotalPrice = (newTotal) => { setCount(Math.round(newTotal / price)); };
return(
<div>
<p>总价: {totalPrice}</p>
<button onClick={() => setTotalPrice(100)}>设置总价为100</button>
</div> );
}
三、模拟 Vue 的 v-model
Vue 的 v-model 是语法糖,本质是 :value + @input,React 里手动实现即可。
1. 基础表单元素(input/textarea)
ini
import { useState } from 'react';
function Demo() {
const [value, setValue] = useState('');
// 等价于 <input v-model="value" />
return (
<input type="text"
value={value}
onChange={(e) => setValue(e.target.value)}
placeholder="请输入内容" /> ); }
2. 自定义组件的双向绑定
React 里通过 value + onChange 实现自定义组件的双向绑定:
javascript
// 自定义输入组件
function CustomInput({ value, onChange }) {
return (
<input type="text"
value={value}
onChange={(e) => onChange(e.target.value)} /> ); }
// 使用组件
function Parent() {
const [text, setText] = useState('');
// 等价于 <CustomInput v-model="text" />
return <CustomInput value={text} onChange={setText} />; }
- 多选框 / 单选框
ini
import { useState } from 'react';
function Demo() {
const [checked, setChecked] = useState(false);
// 等价于 <input type="checkbox" v-model="checked" />
return (
<input
type="checkbox"
checked={checked}
onChange={(e) => setChecked(e.target.checked)}
/> ); }
| Vue 特性 | React 对应实现 | 核心差异 |
|---|---|---|
watch |
useEffect |
需手动指定依赖数组,无内置 deep/immediate 配置 |
computed |
useMemo |
只读缓存,需手动实现 setter |
v-model |
value + onChange |
无语法糖,需手动绑定属性和事件 |