自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

再也不怕面試官問watch、computed、watchEffect的區(qū)別了

開發(fā) 前端
watch?適用于需要有條件地監(jiān)聽數(shù)據(jù)變化的場(chǎng)景,computed?適用于創(chuàng)建派生數(shù)據(jù)和性能優(yōu)化,而watchEffect適用于自動(dòng)追蹤依賴的場(chǎng)景。在實(shí)際應(yīng)用中,根據(jù)具體需求選擇合適的API可以更好地發(fā)揮Vue的響應(yīng)式能力。

在Vue中,數(shù)據(jù)響應(yīng)式是一個(gè)核心概念,它使得當(dāng)數(shù)據(jù)變化時(shí),相關(guān)的視圖會(huì)自動(dòng)更新。為了更靈活地處理數(shù)據(jù)的變化,Vue提供了多種方式,其中包括watch、computed和watchEffect。

watch

watch是Vue中一個(gè)非常強(qiáng)大的特性,它允許你監(jiān)聽數(shù)據(jù)的變化并做出相應(yīng)的反應(yīng)。它有兩種用法:一是監(jiān)聽一個(gè)具體的數(shù)據(jù)變化,二是監(jiān)聽多個(gè)數(shù)據(jù)的變化。

// 監(jiān)聽單個(gè)數(shù)據(jù)
watch('someData', (newVal, oldVal) => {
  // 做一些事情
});

// 監(jiān)聽多個(gè)數(shù)據(jù)
watch(['data1', 'data2'], ([newVal1, newVal2], [oldVal1, oldVal2]) => {
  // 做一些事情
});

watch的實(shí)現(xiàn)原理

Vue中watch的實(shí)現(xiàn)主要依賴于Watcher這個(gè)核心類。當(dāng)調(diào)用watch時(shí),實(shí)際上是創(chuàng)建了一個(gè)Watcher實(shí)例,并將回調(diào)函數(shù)和需要監(jiān)聽的數(shù)據(jù)傳遞給這個(gè)實(shí)例。

// 簡(jiǎn)化版的watch實(shí)現(xiàn)
function watch(source, cb) {
  const watcher = new Watcher(source, cb);
}

Watcher類的構(gòu)造函數(shù)接收兩個(gè)參數(shù),分別是需要監(jiān)聽的數(shù)據(jù)(可以是一個(gè)字符串,也可以是一個(gè)返回值的函數(shù))和回調(diào)函數(shù)。在構(gòu)造函數(shù)中,會(huì)對(duì)數(shù)據(jù)進(jìn)行求值,然后將這個(gè)Watcher實(shí)例添加到數(shù)據(jù)的依賴列表中。

class Watcher {
  constructor(source, cb) {
    this.getter = typeof source === 'function' ? source : () => this.vm[source];
    this.cb = cb;
    this.value = this.get();
  }

  get() {
    pushTarget(this); // 將當(dāng)前Watcher實(shí)例壓棧
    const value = this.getter.call(this.vm); // 觸發(fā)數(shù)據(jù)的getter,將當(dāng)前Watcher實(shí)例添加到依賴列表中
    popTarget(); // 將當(dāng)前Watcher實(shí)例出棧
    return value;
  }

  update() {
    const oldValue = this.value;
    this.value = this.get();
    this.cb(this.value, oldValue);
  }
}

簡(jiǎn)單來(lái)說(shuō),watch的實(shí)現(xiàn)原理就是通過(guò)Watcher實(shí)例來(lái)監(jiān)聽數(shù)據(jù)的變化,當(dāng)數(shù)據(jù)變化時(shí),觸發(fā)update方法執(zhí)行回調(diào)函數(shù)。

computed

computed用于計(jì)算派生數(shù)據(jù)。它依賴于其他響應(yīng)式數(shù)據(jù),并且只有在相關(guān)數(shù)據(jù)發(fā)生變化時(shí)才會(huì)重新計(jì)算。

computed(() => {
  return someData * 2;
});

computed的實(shí)現(xiàn)原理

computed的實(shí)現(xiàn)原理相對(duì)于watch更為復(fù)雜,它依賴于getter和setter的機(jī)制。在Vue中,computed的定義是一個(gè)包含get和set方法的對(duì)象。

const computed = {
  get() {
    return someData * 2;
  },
  set(value) {
    someData = value / 2;
  }
};

在computed的實(shí)現(xiàn)中,當(dāng)訪問計(jì)算屬性時(shí),實(shí)際上是執(zhí)行了get方法,而在數(shù)據(jù)變化時(shí),會(huì)執(zhí)行set方法。這里主要使用了Object.defineProperty這個(gè)JavaScript的特性。

function createComputedGetter() {
  return function computedGetter() {
    const value = getter.call(this); // 執(zhí)行計(jì)算屬性的get方法
    track(target, TrackOpTypes.GET, 'value'); // 添加依賴
    return value;
  };
}

function createComputedSetter() {
  return function computedSetter(newValue) {
    setter.call(this, newValue); // 執(zhí)行計(jì)算屬性的set方法
    trigger(target, TriggerOpTypes.SET, 'value'); // 觸發(fā)更新
  };
}

function computed(getterOrOptions) {
  const getter = 
    typeof getterOrOptions === 'function'
      ? getterOrOptions
      : getterOrOptions.get;

  const setter = getterOrOptions.set;

  const cRef = new ComputedRefImpl(
    getter,
    setter,
    isFunction(getterOrOptions) || !getterOrOptions.get
  );

  return cRef;
}

class ComputedRefImpl {
  // 構(gòu)造函數(shù)
  constructor(getter, setter, isReadonly) {
    // ...
    this.effect = effect(getter, {
      lazy: true,
      scheduler: () => {
        if (!this._dirty) {
          this._dirty = true;
          triggerRef(this);
        }
      },
    });
  }
  // ...
}

在上述代碼中,createComputedGetter和createComputedSetter用于創(chuàng)建計(jì)算屬性的getter和setter。computed函數(shù)接收一個(gè)getter函數(shù),并通過(guò)Object.defineProperty將getter和setter添加到計(jì)算屬性的引用對(duì)象中。

當(dāng)計(jì)算屬性被訪問時(shí),會(huì)觸發(fā)getter,此時(shí)會(huì)將當(dāng)前計(jì)算屬性添加到依賴列表中。當(dāng)計(jì)算屬性的依賴數(shù)據(jù)發(fā)生變化時(shí),會(huì)觸發(fā)setter,并通過(guò)triggerRef觸發(fā)計(jì)算屬性的更新。

watchEffect

watchEffect是Vue 3新增的特性,它用于監(jiān)聽一個(gè)函數(shù)內(nèi)部的響應(yīng)式數(shù)據(jù)變化,當(dāng)變化時(shí),函數(shù)會(huì)被重新執(zhí)行。

watchEffect(() => {
  // 依賴于響應(yīng)式數(shù)據(jù)的操作
});

watchEffect的實(shí)現(xiàn)原理

watchEffect是Vue 3中引入的響應(yīng)式API,它用于執(zhí)行一個(gè)響應(yīng)式函數(shù),并在函數(shù)中響應(yīng)式地追蹤其依賴。與watch不同,watchEffect不需要顯式地指定依賴,它會(huì)自動(dòng)追蹤函數(shù)內(nèi)部的響應(yīng)式數(shù)據(jù),并在這些數(shù)據(jù)變化時(shí)觸發(fā)函數(shù)重新執(zhí)行。

以下是watchEffect的簡(jiǎn)單用法:

import { watchEffect, reactive } from 'vue';

const state = reactive({
  count: 0,
});

watchEffect(() => {
  console.log(state.count);
});

在這個(gè)例子中,watchEffect內(nèi)部的函數(shù)會(huì)自動(dòng)追蹤state.count的變化,并在其變化時(shí)觸發(fā)函數(shù)執(zhí)行。

現(xiàn)在,讓我們來(lái)探討watchEffect的實(shí)現(xiàn)原理。

首先,watchEffect的核心是依賴追蹤和觸發(fā)。Vue 3中的響應(yīng)式系統(tǒng)使用ReactiveEffect類來(lái)表示一個(gè)響應(yīng)式的函數(shù)。

class ReactiveEffect {
  constructor(fn, scheduler = null) {
    // ...
    this.deps = [];
    this.scheduler = scheduler;
  }

  run() {
    // 執(zhí)行響應(yīng)式函數(shù)
    this.active && this.getter();
  }

  stop() {
    // 停止追蹤
    cleanupEffect(this);
  }
}

export function watchEffect(effect, options = {}) {
  // 創(chuàng)建ReactiveEffect實(shí)例
  const runner = effect;
  const job = () => {
    if (!runner.active) {
      return;
    }
    if (cleanup) {
      cleanup();
    }
    // 執(zhí)行響應(yīng)式函數(shù)
    return runner.run();
  };
  // 執(zhí)行響應(yīng)式函數(shù)
  job();
  // 返回停止函數(shù)
  return () => {
    stop(runner);
  };
}

在上述代碼中,ReactiveEffect類表示一個(gè)響應(yīng)式的函數(shù)。watchEffect函數(shù)接收一個(gè)響應(yīng)式函數(shù),并創(chuàng)建一個(gè)ReactiveEffect實(shí)例。在執(zhí)行時(shí),該實(shí)例會(huì)追蹤函數(shù)內(nèi)部的響應(yīng)式數(shù)據(jù),并在這些數(shù)據(jù)變化時(shí)觸發(fā)函數(shù)重新執(zhí)行。

watchEffect返回一個(gè)停止函數(shù),用于停止對(duì)響應(yīng)式數(shù)據(jù)的追蹤。

實(shí)際開發(fā)當(dāng)中該怎么去選擇

watch

watch主要用于監(jiān)聽特定的數(shù)據(jù)變化并執(zhí)行回調(diào)函數(shù)。它可以監(jiān)聽數(shù)據(jù)的變化,并在滿足一定條件時(shí)執(zhí)行相應(yīng)的操作。常見的使用場(chǎng)景包括:

  1. 異步操作觸發(fā):當(dāng)某個(gè)數(shù)據(jù)發(fā)生變化后,需要進(jìn)行異步操作,比如發(fā)起一個(gè)網(wǎng)絡(luò)請(qǐng)求或執(zhí)行一段耗時(shí)的操作。
watch(() => state.data, async (newData, oldData) => {
  // 異步操作
  await fetchData(newData);
});
  1. 深度監(jiān)聽:監(jiān)聽對(duì)象或數(shù)組的變化,并在深層次的數(shù)據(jù)變化時(shí)執(zhí)行回調(diào)。
watch(() => state.user.address.city, (newCity, oldCity) => {
  console.log(`City changed from ${oldCity} to ${newCity}`);
});

computed

computed用于創(chuàng)建一個(gè)計(jì)算屬性,它依賴于其他響應(yīng)式數(shù)據(jù),并且只有在依賴數(shù)據(jù)發(fā)生變化時(shí)才重新計(jì)算。常見的使用場(chǎng)景包括:

  1. 派生數(shù)據(jù):根據(jù)現(xiàn)有的數(shù)據(jù)計(jì)算出一些派生的數(shù)據(jù),而不必每次都重新計(jì)算。
const fullName = computed(() => `${state.firstName} ${state.lastName}`);
  1. 性能優(yōu)化:避免不必要的重復(fù)計(jì)算,提高性能。
const result = computed(() => {
  // 避免重復(fù)計(jì)算
  if (someCondition) {
    return heavyCalculation();
  } else {
    return defaultResult;
  }
});

watchEffect

watchEffect用于執(zhí)行一個(gè)響應(yīng)式函數(shù),并在函數(shù)內(nèi)部自動(dòng)追蹤依賴。它適用于不需要顯式指定依賴,而是在函數(shù)內(nèi)部自動(dòng)追蹤所有響應(yīng)式數(shù)據(jù)變化的場(chǎng)景。常見的使用場(chǎng)景包括:

  1. 自動(dòng)依賴追蹤:函數(shù)內(nèi)部的所有響應(yīng)式數(shù)據(jù)都被自動(dòng)追蹤,無(wú)需顯式指定。
watchEffect(() => {
  console.log(`Count changed to ${state.count}`);
});
  1. 動(dòng)態(tài)數(shù)據(jù)處理:處理動(dòng)態(tài)變化的數(shù)據(jù),無(wú)需手動(dòng)管理依賴。
watchEffect(() => {
  // 處理動(dòng)態(tài)變化的數(shù)據(jù)
  handleDynamicData();
});

總體而言,watch適用于需要有條件地監(jiān)聽數(shù)據(jù)變化的場(chǎng)景,computed適用于創(chuàng)建派生數(shù)據(jù)和性能優(yōu)化,而watchEffect適用于自動(dòng)追蹤依賴的場(chǎng)景。在實(shí)際應(yīng)用中,根據(jù)具體需求選擇合適的API可以更好地發(fā)揮Vue的響應(yīng)式能力。


責(zé)任編輯:武曉燕 來(lái)源: 前端大濕兄
相關(guān)推薦

2021-05-08 07:53:33

面試線程池系統(tǒng)

2022-04-01 07:52:42

JavaScript防抖節(jié)流

2020-11-24 07:48:32

React

2021-08-10 18:36:02

Express原理面試

2020-10-20 09:12:57

axios核心原理

2022-10-31 11:10:49

Javavolatile變量

2020-10-15 12:52:46

SpringbootJava編程語(yǔ)言

2022-08-27 13:49:36

ES7promiseresolve

2020-10-23 09:26:57

React-Redux

2021-04-22 07:49:51

Vue3Vue2.xVue3.x

2022-07-14 08:22:48

Computedvue3

2022-07-11 07:36:36

緩存緩存雪崩緩存擊穿

2021-12-25 22:31:10

MarkWord面試synchronize

2021-11-08 09:18:01

CAS面試場(chǎng)景

2019-06-17 05:03:37

memcache內(nèi)核架構(gòu)

2020-04-30 10:24:35

Spring循環(huán)依賴Java

2021-12-16 18:38:13

面試Synchronize

2020-04-20 15:00:22

DevOps工具代碼

2025-03-10 00:00:00

property?attributeHTML

2025-03-10 11:40:00

前端開發(fā)HTML
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)