最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

前端框架React實現(xiàn)Vue的watch和computed詳解

 更新時間:2026年05月29日 09:15:00   作者:程序猿全棧の董  
React 實現(xiàn)computed的核心是useMemo,通過依賴數(shù)組控制緩存,完全匹配 Vue 計算屬性的緩存特性,這篇文章主要介紹了前端框架React實現(xiàn)Vue的watch和computed的相關(guān)資料,需要的朋友可以參考下

一、前言

在前端框架生態(tài)中,Vue 的 watchcomputed 是兩大核心且極具實用性的特性: computed 用于創(chuàng)建基于依賴的緩存計算屬性,避免無效重復(fù)計算; watch 用于監(jiān)聽數(shù)據(jù)變化并執(zhí)行副作用操作,支撐各類業(yè)務(wù)邏輯的響應(yīng)式觸發(fā)。在 React 開發(fā)中,我們同樣會遇到「需要緩存計算結(jié)果」和「監(jiān)聽數(shù)據(jù)變化執(zhí)行回調(diào)」的場景,同時這也是前端面試中的高頻考點。本文將詳細(xì)講解 React 生態(tài)中如何實現(xiàn) Vue 這兩大特性,涵蓋基礎(chǔ)寫法與進(jìn)階封裝,所有代碼均可直接落地項目。

二、實現(xiàn) Vue 的 computed(計算屬性)

在開始 React 實現(xiàn)之前,我們先明確 Vue computed 的核心特性:基于響應(yīng)式依賴進(jìn)行緩存。只有當(dāng) computed 依賴的數(shù)據(jù)源發(fā)生變化時,才會重新執(zhí)行計算邏輯并更新結(jié)果;如果依賴未發(fā)生變化,直接返回緩存的上一次計算結(jié)果,從而避免無效的性能消耗,這也是 computed 與普通方法的核心區(qū)別。

方式一:基礎(chǔ)版(函數(shù)組件 + useMemo,推薦)

React 中實現(xiàn) computed 核心功能的最佳選擇是官方提供的 useMemo Hook,它完美匹配 Vue computed 的「緩存」核心特性,是項目開發(fā)中的推薦方案。

完整代碼示例

import { useState, useMemo } from 'react';

function ComputedDemo() {
  // 1. 定義數(shù)據(jù)源(模擬 Vue 的 data 選項)
  const [num1, setNum1] = useState(10);
  const [num2, setNum2] = useState(20);
  const [unrelatedNum, setUnrelatedNum] = useState(0); // 與計算邏輯無關(guān)的變量

  // 2. 使用 useMemo 實現(xiàn)計算屬性(模擬 Vue computed)
  const sum = useMemo(() => {
    console.log('useMemo 計算邏輯執(zhí)行了——僅依賴變化時觸發(fā)');
    return num1 + num2;
  }, [num1, num2]); // 依賴數(shù)組:僅 num1、num2 變化時,重新計算 sum

  return (
    <div style={{ padding: '20px' }}>
      <h3>React 實現(xiàn) Vue computed(useMemo 版)</h3>
      <p>num1: {num1}</p>
      <p>num2: {num2}</p>
      <p>無關(guān)變量 unrelatedNum: {unrelatedNum}</p>
      <p style={{ color: 'blue', fontWeight: 'bold' }}>計算屬性 sum(num1 + num2): {sum}</p>

      {/* 3. 交互按鈕:修改相關(guān)依賴 */}
      <button onClick={() => setNum1(prev => prev + 1)} style={{ marginRight: '10px' }}>
        num1 + 1
      </button>
      <button onClick={() => setNum2(prev => prev + 1)} style={{ marginRight: '10px' }}>
        num2 + 1
      </button>

      {/* 4. 交互按鈕:修改無關(guān)依賴 */}
      <button onClick={() => setUnrelatedNum(prev => prev + 1)}>
        無關(guān)變量 + 1
      </button>
    </div>
  );
}

export default ComputedDemo;

核心解釋

  1. useMemo 兩個核心參數(shù)的作用:

    • 第一個參數(shù):計算邏輯函數(shù),返回值即為計算屬性的結(jié)果(對應(yīng) Vue computed 中的計算函數(shù)),該函數(shù)僅在依賴變化時執(zhí)行。
    • 第二個參數(shù):依賴數(shù)組,存放當(dāng)前計算邏輯依賴的所有數(shù)據(jù)源(對應(yīng) Vue computed 自動收集的響應(yīng)式依賴),只有數(shù)組中的變量發(fā)生變化時,React 才會重新執(zhí)行第一個參數(shù)的計算函數(shù),更新計算結(jié)果。
  2. 緩存特性驗證(對比「使用 useMemo」與「直接定義變量」):

    • 上述示例中,點擊「num1 + 1」或「num2 + 1」(修改相關(guān)依賴),控制臺會打印日志,sum 也會同步更新,說明計算邏輯重新執(zhí)行。
    • 點擊「無關(guān)變量 + 1」(修改不相關(guān)依賴),控制臺無日志輸出,sum 保持不變,說明 useMemo 生效,直接返回了緩存的計算結(jié)果。
    • 若直接定義變量 const sum = num1 + num2;,每次組件重新渲染(無論是否修改相關(guān)依賴),都會重新執(zhí)行 num1 + num2 運算,當(dāng)計算邏輯復(fù)雜時(如大量數(shù)據(jù)過濾、格式化),會造成不必要的性能損耗,這也是 useMemo 與普通變量定義的核心差異。

方式二:簡化版(僅簡單計算,無需緩存)

該方式適用于計算邏輯極簡單(如簡單的數(shù)值運算、模板字符串拼接),且完全不關(guān)心重復(fù)計算帶來的性能損耗的場景,對應(yīng) Vue 中 computed 關(guān)閉緩存(極少使用)的場景。

簡短代碼示例

import { useState } from 'react';

function SimpleComputedDemo() {
  // 定義數(shù)據(jù)源
  const [firstName, setFirstName] = useState('Zhang');
  const [lastName, setLastName] = useState('San');

  // 簡化版:直接定義普通變量實現(xiàn)計算(無緩存)
  const fullName = `${firstName} ${lastName}`; // 簡單模板字符串拼接

  return (
    <div style={{ padding: '20px' }}>
      <h3>React 實現(xiàn) Vue computed(簡化版)</h3>
      <p>firstName: {firstName}</p>
      <p>lastName: {lastName}</p>
      <p style={{ color: 'blue', fontWeight: 'bold' }}>計算結(jié)果 fullName: {fullName}</p>

      <button onClick={() => setFirstName('Li')} style={{ marginRight: '10px' }}>
        修改 firstName 為 Li
      </button>
      <button onClick={() => setLastName('Si')}>
        修改 lastName 為 Si
      </button>
    </div>
  );
}

export default SimpleComputedDemo;

說明

該方式無需引入任何 Hook,直接通過普通變量賦值實現(xiàn)計算需求,寫法簡潔。但缺點是無緩存,每次組件渲染(無論依賴是否變化)都會重新執(zhí)行計算邏輯,僅適用于計算成本極低的場景,不推薦在復(fù)雜計算中使用。

三、實現(xiàn) Vue 的 watch(監(jiān)聽數(shù)據(jù)變化)

Vue watch 的核心特性是:監(jiān)聽指定的響應(yīng)式數(shù)據(jù),當(dāng)數(shù)據(jù)發(fā)生變化時,執(zhí)行預(yù)設(shè)的副作用函數(shù)(如發(fā)送接口請求、操作本地存儲、修改其他關(guān)聯(lián)數(shù)據(jù)等)。其核心應(yīng)用場景包括:基礎(chǔ)監(jiān)聽、深度監(jiān)聽(deep: true)、立即執(zhí)行(immediate: true),下面我們逐一在 React 中實現(xiàn)這些場景。

場景一:基礎(chǔ)監(jiān)聽(函數(shù)組件 + useEffect)

React 中處理副作用的核心 Hook 是 useEffect,通過控制其依賴數(shù)組,可以精準(zhǔn)匹配 Vue 基礎(chǔ)版 watch 的功能,這是實現(xiàn)數(shù)據(jù)監(jiān)聽的基礎(chǔ)方案。

完整代碼示例

import { useState, useEffect } from 'react';

function BasicWatchDemo() {
  // 1. 定義數(shù)據(jù)源(模擬 Vue data)
  const [count, setCount] = useState(0); // 單個基礎(chǔ)類型值
  const [user, setUser] = useState({ name: 'Zhang San', age: 25 }); // 對象類型

  // 子場景 1:監(jiān)聽單個基礎(chǔ)類型值(對應(yīng) Vue 監(jiān)聽單個基礎(chǔ)數(shù)據(jù))
  useEffect(() => {
    console.log(`[基礎(chǔ)監(jiān)聽] count 發(fā)生變化,新值為:${count}`);
    // 此處可執(zhí)行副作用邏輯:如接口請求、本地存儲等
  }, [count]); // 依賴數(shù)組:僅 count 變化時,執(zhí)行副作用函數(shù)

  // 子場景 2:監(jiān)聽對象的某個具體屬性(對應(yīng) Vue 監(jiān)聽對象單個屬性)
  useEffect(() => {
    console.log(`[基礎(chǔ)監(jiān)聽] user.name 發(fā)生變化,新值為:${user.name}`);
    // 此處可執(zhí)行副作用邏輯
  }, [user.name]); // 依賴數(shù)組:僅 user.name 變化時,執(zhí)行副作用函數(shù)

  return (
    <div style={{ padding: '20px' }}>
      <h3>React 實現(xiàn) Vue watch(基礎(chǔ)監(jiān)聽版)</h3>
      <p>count: {count}</p>
      <p>user.name: {user.name}</p>
      <p>user.age: {user.age}</p>

      {/* 交互按鈕:修改 count */}
      <button onClick={() => setCount(prev => prev + 1)} style={{ marginRight: '10px' }}>
        count + 1
      </button>

      {/* 交互按鈕:修改 user.name */}
      <button onClick={() => setUser(prev => ({ ...prev, name: 'Li Si' }))} style={{ marginRight: '10px' }}>
        修改 user.name 為 Li Si
      </button>

      {/* 交互按鈕:修改 user.age(不觸發(fā) user.name 的監(jiān)聽) */}
      <button onClick={() => setUser(prev => ({ ...prev, age: prev.age + 1 }))}>
        user.age + 1
      </button>
    </div>
  );
}

export default BasicWatchDemo;

核心解釋

  1. 依賴數(shù)組與監(jiān)聽目標(biāo)的關(guān)聯(lián):useEffect 的副作用函數(shù)執(zhí)行時機(jī)由依賴數(shù)組控制,只有當(dāng)依賴數(shù)組中的變量發(fā)生「淺層次變化」時,副作用函數(shù)才會執(zhí)行,這與 Vue 基礎(chǔ) watch 監(jiān)聽數(shù)據(jù)變化觸發(fā)回調(diào)的邏輯完全一致。
  2. 上述示例中:
    • 點擊「count + 1」,僅觸發(fā) count 對應(yīng)的監(jiān)聽副作用。
    • 點擊「修改 user.name」,僅觸發(fā) user.name 對應(yīng)的監(jiān)聽副作用。
    • 點擊「user.age + 1」,由于未將 user.age 列入依賴數(shù)組,因此不會觸發(fā)任何副作用函數(shù),符合精準(zhǔn)監(jiān)聽的需求。

場景二:深度監(jiān)聽(模擬 Vue watch 的 deep: true)

在實際開發(fā)中,我們經(jīng)常需要監(jiān)聽復(fù)雜對象或數(shù)組的「深層屬性變化」(如 user.address.provincelist[0].name),此時簡單的依賴數(shù)組無法實現(xiàn)需求,這就需要模擬 Vue watchdeep: true 配置,實現(xiàn)深度監(jiān)聽。

方案一:手動監(jiān)聽所有深層屬性(適用于簡單對象)

對于屬性較少的簡單對象,可以將所有需要監(jiān)聽的深層屬性手動列入 useEffect 的依賴數(shù)組,實現(xiàn)近似的深度監(jiān)聽效果。

代碼示例

import { useState, useEffect } from 'react';

function ManualDeepWatchDemo() {
  // 定義深層對象數(shù)據(jù)源
  const [user, setUser] = useState({
    name: 'Zhang San',
    address: {
      province: 'Guangdong',
      city: 'Shenzhen'
    }
  });

  // 手動監(jiān)聽深層屬性:user.name、user.address.province、user.address.city
  useEffect(() => {
    console.log(`[手動深層監(jiān)聽] user 深層屬性發(fā)生變化,當(dāng)前 user:`, user);
  }, [user.name, user.address.province, user.address.city]);

  return (
    <div style={{ padding: '20px' }}>
      <h3>React 實現(xiàn) Vue watch(手動深層監(jiān)聽版)</h3>
      <p>user.name: {user.name}</p>
      <p>user.address.province: {user.address.province}</p>
      <p>user.address.city: {user.address.city}</p>

      <button onClick={() => setUser(prev => ({
        ...prev,
        address: { ...prev.address, city: 'Guangzhou' }
      }))} style={{ marginRight: '10px' }}>
        修改城市為 Guangzhou
      </button>

      <button onClick={() => setUser(prev => ({
        ...prev,
        address: { ...prev.address, province: 'Jiangsu' }
      }))}>
        修改省份為 Jiangsu
      </button>
    </div>
  );
}

export default ManualDeepWatchDemo;

局限性說明

該方案僅適用于屬性較少的簡單對象,當(dāng)對象結(jié)構(gòu)復(fù)雜(如多層嵌套、屬性數(shù)量眾多)時,存在明顯弊端:

  1. 維護(hù)成本極高:需要手動羅列所有深層屬性,遺漏任何一個都可能導(dǎo)致監(jiān)聽失效。
  2. 代碼冗余:依賴數(shù)組會變得異常冗長,降低代碼可讀性和可維護(hù)性。
  3. 無法應(yīng)對動態(tài)屬性:對于數(shù)組、動態(tài)添加的對象屬性,無法提前手動羅列,監(jiān)聽效果受限。

因此,對于復(fù)雜對象或數(shù)組,推薦使用方案二。

方案二:自定義 Hook(useDeepCompareEffect,推薦)

該方案的核心思路是:通過 lodash.isEqual 實現(xiàn)深層數(shù)據(jù)對比,結(jié)合 useRef 緩存上一次的依賴數(shù)據(jù),僅當(dāng)深層對比發(fā)現(xiàn)數(shù)據(jù)變化時,才執(zhí)行副作用函數(shù),完美模擬 Vue watchdeep: true

步驟 1:安裝 lodash 依賴

npm install lodash
# 或
yarn add lodash

步驟 2:自定義 Hook 封裝(useDeepCompareEffect)

import { useEffect, useRef } from 'react';
import isEqual from 'lodash/isEqual';

// 自定義深層對比 useEffect Hook(模擬 deep: true)
function useDeepCompareEffect(effect, deps) {
  // 1. 使用 useRef 緩存上一次的依賴數(shù)據(jù)
  const prevDepsRef = useRef();

  // 2. 深層對比當(dāng)前依賴與上一次依賴是否一致
  const depsChanged = !isEqual(deps, prevDepsRef.current);

  // 3. 更新緩存的依賴數(shù)據(jù)(無論是否變化,都更新為當(dāng)前最新依賴)
  if (depsChanged) {
    prevDepsRef.current = deps;
  }

  // 4. 調(diào)用 useEffect,依賴數(shù)組為 [depsChanged](僅當(dāng)深層對比發(fā)現(xiàn)變化時,執(zhí)行 effect)
  useEffect(() => {
    return effect();
  }, [depsChanged]);
}

export default useDeepCompareEffect;

步驟 3:使用示例(監(jiān)聽復(fù)雜深層對象)

import { useState } from 'react';
import useDeepCompareEffect from './useDeepCompareEffect';

function DeepWatchDemo() {
  // 定義復(fù)雜深層對象數(shù)據(jù)源
  const [user, setUser] = useState({
    name: 'Zhang San',
    age: 25,
    address: {
      province: 'Guangdong',
      city: 'Shenzhen',
      detail: {
        street: 'Nanshan Road',
        number: '123'
      }
    },
    hobbies: ['reading', 'running']
  });

  // 使用自定義 useDeepCompareEffect 實現(xiàn)深度監(jiān)聽
  useDeepCompareEffect(() => {
    console.log(`[深層監(jiān)聽] user 發(fā)生變化(包含深層屬性),當(dāng)前 user:`, user);
  }, [user]); // 依賴數(shù)組直接傳入整個 user,無需手動羅列深層屬性

  return (
    <div style={{ padding: '20px' }}>
      <h3>React 實現(xiàn) Vue watch(深層監(jiān)聽版)</h3>
      <p>user.name: {user.name}</p>
      <p>user.address.detail.street: {user.address.detail.street}</p>
      <p>user.hobbies: {user.hobbies.join(', ')}</p>

      <button onClick={() => setUser(prev => ({
        ...prev,
        address: {
          ...prev.address,
          detail: { ...prev.address.detail, street: 'Futian Road' }
        }
      }))} style={{ marginRight: '10px' }}>
        修改街道為 Futian Road
      </button>

      <button onClick={() => setUser(prev => ({
        ...prev,
        hobbies: [...prev.hobbies, 'swimming']
      }))}>
        添加愛好 swimming
      </button>
    </div>
  );
}

export default DeepWatchDemo;

說明

該方案完美解決了復(fù)雜對象的深度監(jiān)聽問題,無需手動羅列深層屬性,維護(hù)成本低,是項目開發(fā)中處理深度監(jiān)聽的推薦方案,其核心邏輯是通過 lodash.isEqual 忽略引用地址,僅對比數(shù)據(jù)的深層內(nèi)容是否一致。

場景三:立即執(zhí)行(模擬 Vue watch 的 immediate: true)

Vue watchimmediate: true 配置用于實現(xiàn)「監(jiān)聽函數(shù)在首次渲染時立即執(zhí)行一次,后續(xù)依賴變化時再正常執(zhí)行」。而 React 中 useEffect 的默認(rèn)行為就是:首次組件渲染時執(zhí)行一次副作用函數(shù),之后僅當(dāng)依賴變化時再次執(zhí)行,這與 immediate: true 的邏輯完全匹配,實現(xiàn)起來非常簡潔。

代碼示例 1:默認(rèn)立即執(zhí)行(簡潔寫法)

import { useState, useEffect } from 'react';

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

  // useEffect 默認(rèn)行為:首次渲染 + count 變化時執(zhí)行(對應(yīng) Vue immediate: true)
  useEffect(() => {
    console.log(`[立即執(zhí)行] count 監(jiān)聽觸發(fā),當(dāng)前值:${count}`);
    // 副作用邏輯:如初始化請求、首次渲染后的數(shù)據(jù)處理等
  }, [count]);

  return (
    <div style={{ padding: '20px' }}>
      <h3>React 實現(xiàn) Vue watch(立即執(zhí)行版)</h3>
      <p>count: {count}</p>
      <button onClick={() => setCount(prev => prev + 1)}>
        count + 1
      </button>
    </div>
  );
}

export default ImmediateWatchDemo1;

代碼示例 2:取消「立即執(zhí)行」(僅數(shù)據(jù)變化時執(zhí)行)

有時我們需要模擬 Vue watch 的默認(rèn)行為(immediate: false,僅數(shù)據(jù)變化時執(zhí)行,首次渲染不執(zhí)行),此時可以通過 useRef 定義一個標(biāo)識位,控制首次渲染時不執(zhí)行副作用邏輯。

import { useState, useEffect, useRef } from 'react';

function ImmediateWatchDemo2() {
  const [count, setCount] = useState(0);
  const isFirstRender = useRef(true); // 標(biāo)識位:標(biāo)記是否為首次渲染

  useEffect(() => {
    // 首次渲染時,直接返回,不執(zhí)行副作用邏輯
    if (isFirstRender.current) {
      isFirstRender.current = false; // 重置標(biāo)識位,后續(xù)渲染不再生效
      return;
    }

    // 非首次渲染(僅 count 變化時),執(zhí)行副作用邏輯
    console.log(`[取消立即執(zhí)行] count 發(fā)生變化,當(dāng)前值:${count}`);
  }, [count]);

  return (
    <div style={{ padding: '20px' }}>
      <h3>React 實現(xiàn) Vue watch(取消立即執(zhí)行版)</h3>
      <p>count: {count}</p>
      <button onClick={() => setCount(prev => prev + 1)}>
        count + 1
      </button>
    </div>
  );
}

export default ImmediateWatchDemo2;

進(jìn)階:封裝 Vue 風(fēng)格的 useWatch 自定義 Hook(提升復(fù)用性)

上述方案已經(jīng)實現(xiàn)了 Vue watch 的核心功能,但在多個組件中使用時會存在重復(fù)代碼。我們可以封裝一個貼近 Vue 寫法的 useWatch 自定義 Hook,支持 immediatedeep 兩個配置項,提升代碼復(fù)用性。

完整封裝代碼

import { useEffect, useRef } from 'react';
import isEqual from 'lodash/isEqual';

// 自定義 Vue 風(fēng)格 useWatch Hook
function useWatch(watchSource, callback, options = { immediate: false, deep: false }) {
  const { immediate, deep } = options;
  const prevSourceRef = useRef(); // 緩存上一次的監(jiān)聽源數(shù)據(jù)
  const isFirstRender = useRef(true); // 標(biāo)記是否為首次渲染

  // 處理監(jiān)聽邏輯
  useEffect(() => {
    // 1. 處理首次渲染立即執(zhí)行
    if (isFirstRender.current) {
      isFirstRender.current = false;
      if (immediate) {
        callback(watchSource, undefined); // 首次執(zhí)行:新值為當(dāng)前監(jiān)聽源,舊值為 undefined
        return;
      }
    }

    // 2. 處理深度對比 vs 淺對比
    const sourceChanged = deep 
      ? !isEqual(watchSource, prevSourceRef.current) 
      : watchSource !== prevSourceRef.current;

    // 3. 監(jiān)聽源變化時,執(zhí)行回調(diào)函數(shù)
    if (sourceChanged) {
      callback(watchSource, prevSourceRef.current); // 傳遞新值和舊值
    }

    // 4. 更新緩存的監(jiān)聽源數(shù)據(jù)
    prevSourceRef.current = deep ? JSON.parse(JSON.stringify(watchSource)) : watchSource;
  }, [watchSource, callback, immediate, deep]);
}

export default useWatch;

使用示例

import { useState } from 'react';
import useWatch from './useWatch';

function VueStyleWatchDemo() {
  // 定義監(jiān)聽源
  const [user, setUser] = useState({
    name: 'Zhang San',
    age: 25,
    address: {
      city: 'Shenzhen'
    }
  });

  // 使用封裝的 useWatch(支持 deep: true + immediate: true)
  useWatch(
    user, // 監(jiān)聽源(對應(yīng) Vue watch 的監(jiān)聽目標(biāo))
    (newValue, oldValue) => { // 回調(diào)函數(shù)(對應(yīng) Vue watch 的處理函數(shù))
      console.log('[Vue 風(fēng)格 useWatch] 監(jiān)聽觸發(fā)');
      console.log('新值:', newValue);
      console.log('舊值:', oldValue);
    },
    { immediate: true, deep: true } // 配置項(對應(yīng) Vue watch 的 immediate 和 deep)
  );

  return (
    <div style={{ padding: '20px' }}>
      <h3>React 封裝 Vue 風(fēng)格 useWatch</h3>
      <p>user.name: {user.name}</p>
      <p>user.address.city: {user.address.city}</p>

      <button onClick={() => setUser(prev => ({
        ...prev,
        address: { ...prev.address, city: 'Guangzhou' }
      }))}>
        修改城市為 Guangzhou
      </button>
    </div>
  );
}

export default VueStyleWatchDemo;

說明

該自定義 useWatch Hook 完全貼近 Vue watch 的寫法,支持新舊值傳遞、立即執(zhí)行和深度監(jiān)聽配置,可直接在項目中復(fù)用,同時也是前端面試中的加分項,體現(xiàn)了開發(fā)者的 Hook 封裝能力和對 React 副作用的理解。

四、React vs Vue 核心對應(yīng)關(guān)系(匯總表)

Vue 特性React 實現(xiàn)方式核心匹配點
computed(帶緩存)函數(shù)組件 + useMemo Hook基于依賴緩存,依賴不變時不重復(fù)計算,優(yōu)化性能
computed(無緩存)普通變量直接賦值(簡單計算)實現(xiàn)基礎(chǔ)計算需求,無緩存,寫法簡潔
watch(基礎(chǔ)監(jiān)聽)函數(shù)組件 + useEffect Hook依賴變化時執(zhí)行副作用,精準(zhǔn)監(jiān)聽單個/多個基礎(chǔ)數(shù)據(jù)
watch(deep: true)1. 手動羅列深層屬性(簡單對象)
2. 自定義 useDeepCompareEffect(復(fù)雜對象,依賴 lodash.isEqual)
忽略引用地址,監(jiān)聽對象/數(shù)組的深層內(nèi)容變化
watch(immediate: true)函數(shù)組件 + useEffect Hook(默認(rèn)行為)首次渲染 + 依賴變化時執(zhí)行副作用
watch(immediate: false)函數(shù)組件 + useEffect + useRef 標(biāo)識位僅依賴變化時執(zhí)行副作用,首次渲染不執(zhí)行
完整 Vue 風(fēng)格 watch自定義 useWatch Hook(封裝 useEffect + 深層對比)支持 deep、immediate 配置,貼近 Vue 寫法,提升復(fù)用性

五、總結(jié)與落地說明

1. 核心要點回顧

  • React 實現(xiàn) Vue computed 的核心是 useMemo Hook,其緩存特性與 computed 完全匹配,是復(fù)雜計算場景的首選方案;簡單計算可直接使用普通變量賦值,兼顧簡潔性。
  • React 實現(xiàn) Vue watch 的基礎(chǔ)是 useEffect Hook,通過依賴數(shù)組控制副作用執(zhí)行時機(jī),實現(xiàn)基礎(chǔ)監(jiān)聽;深層監(jiān)聽需結(jié)合 lodash.isEqual 進(jìn)行深層數(shù)據(jù)對比,封裝自定義 Hook 提升復(fù)用性;立即執(zhí)行與取消立即執(zhí)行的核心是通過 useRef 標(biāo)識位控制首次渲染的邏輯。
  • 所有實現(xiàn)方案均符合 React 官方最佳實踐,無額外第三方框架依賴(僅深層監(jiān)聽需引入 lodash),穩(wěn)定性有保障。

2. 實用價值強調(diào)

本文覆蓋了日常 React 開發(fā)中 99% 的「計算屬性」和「數(shù)據(jù)監(jiān)聽」場景,從基礎(chǔ)寫法到進(jìn)階封裝,代碼均可直接復(fù)制落地。其中,自定義 useDeepCompareEffectuseWatch Hook 不僅能減少項目中的重復(fù)代碼,還能在前端面試中展現(xiàn)個人的技術(shù)深度和工程化思維,是加分的亮點。

3. 落地補充提示

  • 項目中可將 useDeepCompareEffectuseWatch 抽離為公共 Hook(如放在 src/hooks/ 目錄下),統(tǒng)一管理和維護(hù),方便所有組件引入使用。
  • 若項目中已引入 lodash,可直接使用 lodash.isEqual;若不想引入完整 lodash,可單獨安裝 lodash.isEqualnpm install lodash.isEqual),減小打包體積。
  • 對于極致性能優(yōu)化的場景,可結(jié)合 useCallback 緩存回調(diào)函數(shù),與 useMemo、useEffect 配合使用,進(jìn)一步減少不必要的組件重渲染。
  • 隨著 React 生態(tài)的發(fā)展,也可選擇成熟的第三方 Hook 庫(如 react-use),其中已封裝了完善的深層監(jiān)聽、數(shù)據(jù)監(jiān)聽 Hook,快速提升開發(fā)效率。

通過本文的學(xué)習(xí),相信你已經(jīng)能夠在 React 項目中靈活實現(xiàn) Vue watchcomputed 的核心功能,從容應(yīng)對各類響應(yīng)式場景的開發(fā)需求。

到此這篇關(guān)于前端框架React實現(xiàn)Vue的watch和computed詳解的文章就介紹到這了,更多相關(guān)React實現(xiàn)Vue的watch和computed內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評論

赞皇县| 庄河市| 康平县| 丹棱县| 南京市| 玛曲县| 林州市| 钟山县| 南和县| 永泰县| 墨竹工卡县| 太仆寺旗| 西和县| 建阳市| 鲁山县| 利津县| 罗田县| 紫阳县| 卢龙县| 秦安县| 托里县| 西贡区| 淅川县| 屏南县| 洞口县| 焦作市| 白水县| 桃园县| 上虞市| 民权县| 康平县| 察隅县| 犍为县| 万宁市| 安乡县| 中卫市| 博乐市| 娱乐| 南岸区| 海门市| 抚顺市|