Vue3 中的数据侦测的实现

yizhihongxing

Vue3 中的数据侦测是通过 Proxy 实现的。当我们创建一个响应式对象时,Vue3 内部会使用 Proxy 将其转化成一个响应式对象。当我们访问对象中的属性时,Vue3 会自动追踪这个属性,并将这个属性添加到依赖列表中。当响应式对象中的属性发生改变时,Vue3 就会更新视图。

下面我们来看具体的实现步骤:

使用 createReactiveObject 创建响应式对象

Vue3 使用 createReactiveObject 来创建响应式对象。createReactiveObject 函数接受 3 个参数:target、proxy、baseHandlers。其中,target 是我们要转化为响应式的对象,proxy 是一个 Proxy 实例,baseHandlers 是一个包含 get 和 set 函数的对象。

const target = {};
const proxy = new Proxy(target, baseHandlers);
const baseHandlers = {
  get: function(target, prop) {
    // get方法实现省略...
  },
  set: function(target, prop, value) {
    // set方法实现省略...
  }
};
const reactiveObj = createReactiveObject(target, proxy, baseHandlers);

实现 get 和 set 方法

我们需要在 baseHandlers 中实现 get 和 set 方法来拦截对象的读取和设置操作。

针对访问操作,get 方法应该执行以下操作:

  • 获取属性值并返回。
  • 如果当前属性只能读取而无法修改,则不将其添加到依赖列表中。
const baseHandlers = {
  get: function(target, prop, receiver) {
    let value = Reflect.get(target, prop, receiver);
    // 将当前属性添加到依赖列表中
    track(target, 'get', prop);
    return value;
  },
  set: function(target, prop, value, receiver) {
    let oldValue = Reflect.get(target, prop, receiver);
    let res = Reflect.set(target, prop, value, receiver);
    // 将当前属性对应的依赖列表中的所有 effect 都执行一遍
    trigger(target, prop, value, oldValue);
    return res;
  }
};

针对修改操作,set 方法应该执行以下操作:

  • 设置属性值。
  • 将当前属性对应的依赖列表中的所有 effect 都执行一遍。

追踪依赖项

我们需要在 track 函数中实现依赖追踪功能。track 函数接受 3 个参数:target、type、key。其中,target 是我们要追踪的对象,type 是追踪类型(取值可以为 'get' 和 'set'),key 是我们追踪的属性名称。

let activeEffect = null;
const targetMap = new WeakMap();

function track(target, type, key) {
  // 如果不存在活跃的 effect,则直接返回
  if (!activeEffect) {
    return;
  }
  let depsMap = targetMap.get(target);
  // 如果当前对象还没有依赖列表,则创建一个新的依赖列表
  if (!depsMap) {
    depsMap = new Map();
    targetMap.set(target, depsMap);
  }
  let dep = depsMap.get(key);
  // 如果当前属性还没有依赖列表,则创建一个新的依赖列表
  if (!dep) {
    dep = new Set();
    depsMap.set(key, dep);
  }
  // 把当前活跃的 effect 添加到依赖列表中
  dep.add(activeEffect);
}

触发更新

我们需要在 trigger 函数中实现更新操作。trigger 函数接收 4 个参数:target、key、newValue、oldValue。其中,target 是我们要更新的对象,key 是我们要更新的属性名称,newValue 是更新后的新值,oldValue 是更新前的旧值。

function trigger(target, key, newValue, oldValue) {
  let depsMap = targetMap.get(target);
  if (!depsMap) {
    // 当前对象没有依赖列表,说明没有 effect 依赖当前对象,则直接返回
    return;
  }
  let dep = depsMap.get(key);
  if (dep) {
    // 如果当前属性对应的依赖列表中存在 effect,则执行这些 effect
    dep.forEach(effect => {
      effect(target, key, newValue, oldValue);
    });
  }
}

以上是 Vue3 中数据侦测的实现过程,下面给出具体的示例代码。

示例一

在这个示例中,我们创建一个响应式的对象 obj,当我们读取 obj 的属性时,它会自动添加到依赖列表中。

let target = { a: 1 };
let reactiveObj = reactive(target);

effect(() => {
  console.log(reactiveObj.a);
});

// 控制台输出:1

示例二

在这个示例中,我们创建一个响应式的对象 obj,然后我们通过改变 obj 中的值,触发依赖列表中的函数执行。

let target = { a: 1 };
let reactiveObj = reactive(target);

effect(() => {
  console.log(reactiveObj.a);
});

reactiveObj.a = 2; // 控制台输出:2

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Vue3 中的数据侦测的实现 - Python技术站

(0)
上一篇 2023年5月27日
下一篇 2023年5月27日

相关文章

  • Vue+Vux项目实践完整代码

    Vue+Vux项目实践完整代码攻略 1. 前置知识 在进行Vue+Vux开发前,需要掌握以下基础知识: HTML、CSS、JavaScript基础语法 Vue.js框架基础语法 Vuex状态管理库基础语法 NPM包管理器基础命令 2. 安装Vue+Vux 在开始编写代码之前,需要先安装Vue.js和Vux,具体步骤如下: 安装Vue.js npm insta…

    Vue 2023年5月27日
    00
  • Vue3 Vant组件库使用过程中的避坑点

    下面是详细讲解Vue3 Vant组件库使用过程中的避坑点的完整攻略: 1. 导入组件时注意组件名称 在使用Vant组件库时,要注意组件名称的大小写问题。在Vue3中,组件名称必须采用小写字母加横线的形式。而在Vant组件库中,组件名称采用的是带有大写字母的驼峰式命名。这就需要我们在使用Vant组件时进行一些转换。 例如,在使用Tab栏组件时,如果我们想使用命…

    Vue 2023年5月29日
    00
  • Vue 组件(component)教程之实现精美的日历方法示例

    针对“Vue 组件(component)教程之实现精美的日历方法示例”,我可以介绍它的完整攻略,包括以下几部分内容: 理解 Vue 组件 在进入日历组件的实现前,首先需要理解什么是 Vue 组件。Vue 组件是 Vue.js 中的基本概念,它可以把一个页面拆分成若干独立、可重用的模块,并将这些模块进行拼装组合成为一个完整的页面。因此,理解 Vue 组件的分类…

    Vue 2023年5月28日
    00
  • vue之webpack -v报错解决方案总结

    下面是“vue之webpack -v报错解决方案总结”的完整攻略。 问题描述 在使用Vue CLI创建项目或运行已有项目时,可能会出现以下错误提示: sh: webpack: command not found 这个错误提示表示无法找到webpack命令,这将导致无法完成项目的构建和打包。 解决方案 方案一:全局安装webpack 可以尝试全局安装最新版本的…

    Vue 2023年5月28日
    00
  • vue最简单的前后端交互示例详解

    下面是“vue最简单的前后端交互示例详解”的完整攻略。 总览 前后端交互是Web开发中的重要环节,Vue作为现代化的前端框架,提供了多种方式来与后端服务交互。本文将会介绍Vue前端框架如何处理前后端交互,包括如何发送Ajax请求、获取/提交数据等。 准备工作 在开始前,我们需要先了解以下基础知识: Vue.js基础语法 前端模块化开发 发送Ajax请求 我们…

    Vue 2023年5月28日
    00
  • vue中如何下载excel流文件及设置下载文件名

    下面我将详细讲解一下“Vue中如何下载Excel流文件及设置下载文件名”的攻略。 方案1:使用FileSaver.js库 安装 我们需要先安装FileSaver.js库,可以使用npm安装: npm install file-saver –save 具体实现 在需要下载Excel文件的地方,我们可以创建一个Blob对象,用于存储Excel文件的二进制数据。…

    Vue 2023年5月28日
    00
  • 谈谈vue中mixin的一点理解

    下面是对 “谈谈vue中mixin的一点理解” 的详细讲解: 什么是mixin 在Vue中,mixin指的是混入,也就是将一些可复用的代码,抽象出来,在多个组件之间进行共享。可以理解为抽象出来的一些特性集合。mixin可以包含组件中的各种选项,并且最终会和组件选项合并,优先级高于组件选项。 如何使用mixin 在Vue中使用mixin非常简单。我们可以先定义…

    Vue 2023年5月29日
    00
  • vue todo-list组件发布到npm上的方法

    发布vue todo-list组件到npm上的步骤如下: 步骤一:创建项目 首先,在本地环境选择一个合适的位置创建一个新项目文件夹,使用命令行工具进入该文件夹。执行以下命令来创建一个新的npm项目: npm init 该命令会让你输入新项目的一些基本信息,并生成一个package.json文件。 步骤二:编写代码 在创建好的项目文件夹下,按照vue组件编写流…

    Vue 2023年5月28日
    00
合作推广
合作推广
分享本页
返回顶部