当前位置:首页 > 科技  > 软件

再也不怕面试官问watch、computed、watchEffect的区别了

来源: 责编: 时间:2023-11-30 09:30:28 338观看
导读在Vue中,数据响应式是一个核心概念,它使得当数据变化时,相关的视图会自动更新。为了更灵活地处理数据的变化,Vue提供了多种方式,其中包括watch、computed和watchEffect。watchwatch是Vue中一个非常强大的特性,它允许你监听

在Vue中,数据响应式是一个核心概念,它使得当数据变化时,相关的视图会自动更新。为了更灵活地处理数据的变化,Vue提供了多种方式,其中包括watch、computed和watchEffect。3zY28资讯网——每日最新资讯28at.com

watch

watch是Vue中一个非常强大的特性,它允许你监听数据的变化并做出相应的反应。它有两种用法:一是监听一个具体的数据变化,二是监听多个数据的变化。3zY28资讯网——每日最新资讯28at.com

// 监听单个数据watch('someData', (newVal, oldVal) => {  // 做一些事情});// 监听多个数据watch(['data1', 'data2'], ([newVal1, newVal2], [oldVal1, oldVal2]) => {  // 做一些事情});

watch的实现原理

Vue中watch的实现主要依赖于Watcher这个核心类。当调用watch时,实际上是创建了一个Watcher实例,并将回调函数和需要监听的数据传递给这个实例。3zY28资讯网——每日最新资讯28at.com

// 简化版的watch实现function watch(source, cb) {  const watcher = new Watcher(source, cb);}

Watcher类的构造函数接收两个参数,分别是需要监听的数据(可以是一个字符串,也可以是一个返回值的函数)和回调函数。在构造函数中,会对数据进行求值,然后将这个Watcher实例添加到数据的依赖列表中。3zY28资讯网——每日最新资讯28at.com

class Watcher {  constructor(source, cb) {    this.getter = typeof source === 'function' ? source : () => this.vm[source];    this.cb = cb;    this.value = this.get();  }  get() {    pushTarget(this); // 将当前Watcher实例压栈    const value = this.getter.call(this.vm); // 触发数据的getter,将当前Watcher实例添加到依赖列表中    popTarget(); // 将当前Watcher实例出栈    return value;  }  update() {    const oldValue = this.value;    this.value = this.get();    this.cb(this.value, oldValue);  }}

简单来说,watch的实现原理就是通过Watcher实例来监听数据的变化,当数据变化时,触发update方法执行回调函数。3zY28资讯网——每日最新资讯28at.com

computed

computed用于计算派生数据。它依赖于其他响应式数据,并且只有在相关数据发生变化时才会重新计算。3zY28资讯网——每日最新资讯28at.com

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

computed的实现原理

computed的实现原理相对于watch更为复杂,它依赖于getter和setter的机制。在Vue中,computed的定义是一个包含get和set方法的对象。3zY28资讯网——每日最新资讯28at.com

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

在computed的实现中,当访问计算属性时,实际上是执行了get方法,而在数据变化时,会执行set方法。这里主要使用了Object.defineProperty这个JavaScript的特性。3zY28资讯网——每日最新资讯28at.com

function createComputedGetter() {  return function computedGetter() {    const value = getter.call(this); // 执行计算属性的get方法    track(target, TrackOpTypes.GET, 'value'); // 添加依赖    return value;  };}function createComputedSetter() {  return function computedSetter(newValue) {    setter.call(this, newValue); // 执行计算属性的set方法    trigger(target, TriggerOpTypes.SET, 'value'); // 触发更新  };}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 {  // 构造函数  constructor(getter, setter, isReadonly) {    // ...    this.effect = effect(getter, {      lazy: true,      scheduler: () => {        if (!this._dirty) {          this._dirty = true;          triggerRef(this);        }      },    });  }  // ...}

在上述代码中,createComputedGetter和createComputedSetter用于创建计算属性的getter和setter。computed函数接收一个getter函数,并通过Object.defineProperty将getter和setter添加到计算属性的引用对象中。3zY28资讯网——每日最新资讯28at.com

当计算属性被访问时,会触发getter,此时会将当前计算属性添加到依赖列表中。当计算属性的依赖数据发生变化时,会触发setter,并通过triggerRef触发计算属性的更新。3zY28资讯网——每日最新资讯28at.com

watchEffect

watchEffect是Vue 3新增的特性,它用于监听一个函数内部的响应式数据变化,当变化时,函数会被重新执行。3zY28资讯网——每日最新资讯28at.com

watchEffect(() => {  // 依赖于响应式数据的操作});

watchEffect的实现原理

watchEffect是Vue 3中引入的响应式API,它用于执行一个响应式函数,并在函数中响应式地追踪其依赖。与watch不同,watchEffect不需要显式地指定依赖,它会自动追踪函数内部的响应式数据,并在这些数据变化时触发函数重新执行。3zY28资讯网——每日最新资讯28at.com

以下是watchEffect的简单用法:3zY28资讯网——每日最新资讯28at.com

import { watchEffect, reactive } from 'vue';const state = reactive({  count: 0,});watchEffect(() => {  console.log(state.count);});

在这个例子中,watchEffect内部的函数会自动追踪state.count的变化,并在其变化时触发函数执行。3zY28资讯网——每日最新资讯28at.com

现在,让我们来探讨watchEffect的实现原理。3zY28资讯网——每日最新资讯28at.com

首先,watchEffect的核心是依赖追踪和触发。Vue 3中的响应式系统使用ReactiveEffect类来表示一个响应式的函数。3zY28资讯网——每日最新资讯28at.com

class ReactiveEffect {  constructor(fn, scheduler = null) {    // ...    this.deps = [];    this.scheduler = scheduler;  }  run() {    // 执行响应式函数    this.active && this.getter();  }  stop() {    // 停止追踪    cleanupEffect(this);  }}export function watchEffect(effect, options = {}) {  // 创建ReactiveEffect实例  const runner = effect;  const job = () => {    if (!runner.active) {      return;    }    if (cleanup) {      cleanup();    }    // 执行响应式函数    return runner.run();  };  // 执行响应式函数  job();  // 返回停止函数  return () => {    stop(runner);  };}

在上述代码中,ReactiveEffect类表示一个响应式的函数。watchEffect函数接收一个响应式函数,并创建一个ReactiveEffect实例。在执行时,该实例会追踪函数内部的响应式数据,并在这些数据变化时触发函数重新执行。3zY28资讯网——每日最新资讯28at.com

watchEffect返回一个停止函数,用于停止对响应式数据的追踪。3zY28资讯网——每日最新资讯28at.com

实际开发当中该怎么去选择

watch

watch主要用于监听特定的数据变化并执行回调函数。它可以监听数据的变化,并在满足一定条件时执行相应的操作。常见的使用场景包括:3zY28资讯网——每日最新资讯28at.com

  1. 异步操作触发:当某个数据发生变化后,需要进行异步操作,比如发起一个网络请求或执行一段耗时的操作。
watch(() => state.data, async (newData, oldData) => {  // 异步操作  await fetchData(newData);});
  1. 深度监听:监听对象或数组的变化,并在深层次的数据变化时执行回调。
watch(() => state.user.address.city, (newCity, oldCity) => {  console.log(`City changed from ${oldCity} to ${newCity}`);});

computed

computed用于创建一个计算属性,它依赖于其他响应式数据,并且只有在依赖数据发生变化时才重新计算。常见的使用场景包括:3zY28资讯网——每日最新资讯28at.com

  1. 派生数据:根据现有的数据计算出一些派生的数据,而不必每次都重新计算。
const fullName = computed(() => `${state.firstName} ${state.lastName}`);
  1. 性能优化:避免不必要的重复计算,提高性能。
const result = computed(() => {  // 避免重复计算  if (someCondition) {    return heavyCalculation();  } else {    return defaultResult;  }});

watchEffect

watchEffect用于执行一个响应式函数,并在函数内部自动追踪依赖。它适用于不需要显式指定依赖,而是在函数内部自动追踪所有响应式数据变化的场景。常见的使用场景包括:3zY28资讯网——每日最新资讯28at.com

  1. 自动依赖追踪:函数内部的所有响应式数据都被自动追踪,无需显式指定。
watchEffect(() => {  console.log(`Count changed to ${state.count}`);});
  1. 动态数据处理:处理动态变化的数据,无需手动管理依赖。
watchEffect(() => {  // 处理动态变化的数据  handleDynamicData();});

总体而言,watch适用于需要有条件地监听数据变化的场景,computed适用于创建派生数据和性能优化,而watchEffect适用于自动追踪依赖的场景。在实际应用中,根据具体需求选择合适的API可以更好地发挥Vue的响应式能力。3zY28资讯网——每日最新资讯28at.com


3zY28资讯网——每日最新资讯28at.com

本文链接:http://www.28at.com/showinfo-26-35340-0.html再也不怕面试官问watch、computed、watchEffect的区别了

声明:本网页内容旨在传播知识,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。邮件:2376512515@qq.com

上一篇: 八股文-如何理解Java中的多态

下一篇: 再见,Shiro !你好,Sa-Token!

标签:
  • 热门焦点
  • 之家push系统迭代之路

    前言在这个信息爆炸的互联网时代,能够及时准确获取信息是当今社会要解决的关键问题之一。随着之家用户体量和内容规模的不断增大,传统的靠"主动拉"获取信息的方式已不能满足用
  • 只需五步,使用start.spring.io快速入门Spring编程

    步骤1打开https://start.spring.io/,按照屏幕截图中的内容创建项目,添加 Spring Web 依赖项,并单击“生成”按钮下载 .zip 文件,为下一步做准备。请在进入步骤2之前进行解压。图
  • 小红书1周涨粉49W+,我总结了小白可以用的N条涨粉笔记

    作者:黄河懂运营一条性教育视频,被54万人“珍藏”是什么体验?最近,情感博主@公主是用鲜花做的,火了!仅仅凭借一条视频,光小红书就有超过128万人,为她疯狂点赞!更疯狂的是,这
  • 大厂卷向扁平化

    来源:新熵作者丨南枝 编辑丨月见大厂职级不香了。俗话说,兵无常势,水无常形,互联网企业调整职级体系并不稀奇。7月13日,淘宝天猫集团启动了近年来最大的人力制度改革,目前已形成一
  • ESG的面子与里子

    来源 | 光子星球撰文 | 吴坤谚编辑 | 吴先之三伏大幕拉起,各地高温预警不绝,但处于厄尔尼诺大“烤”之下的除了众生,还有各大企业发布的ESG报告。ESG是“环境保
  • OPPO、vivo、小米等国内厂商Q2在印度智能手机市场份额依旧高达55%

    7月20日消息,据外媒报道,研究机构的报告显示,在全球智能手机出货量同比仍在下滑的大背景下,印度这一有潜力的市场也未能幸免,出货量同比也有下滑,多家厂
  • 小米汽车电池信息疑似曝光:容量101kWh,支持800V高压快充

    7月14日消息,今日一名博主在社交媒体发布了一张疑似小米汽车电池信息的照片,显示该电池包正是宁德时代麒麟电池,容量为101kWh,电压为726.7V,可以预测小
  • 世界人工智能大会国际日开幕式活动在世博展览馆开启

    30日上午,世界人工智能大会国际日开幕式活动在世博展览馆开启,聚集国际城市代表、重量级院士专家、国际创新企业代表,共同打造人工智能交流平台。上海市副市
  • 利用职权私自解除被封帐号 Meta开除20多名员工

    11月18日消息,据外媒援引知情人士表示,过去一年时间内,Facebook母公司Meta解雇或处罚了20多名员工以及合同工,指控这些人通过内部系统以不当方式重置用户帐号,其
Top