Vue2和vue3中双向数据绑定的原理,ES6的Proxy对象代理和JavaScript的Object.defineProperty,使用详细

news/2024/11/23 4:18:49/

简介:Object.defineProperty大家都知道,是vue2中双向数据绑定的原理,它是 JavaScript 中一个强大且常用的方法,用于定义对象属性,允许我们精确地控制属性的行为,包括读取、写入和删除等操作;

而Proxy是vue3中双向数据绑定的原理,是ES6中一种用于创建代理对象的特殊对象,它允许我们拦截并自定义目标对象的操作,例如属性访问、赋值、函数调用等。Proxy提供了一种机制,可以在目标对象上设置拦截器,从而拦截对目标对象的操作。

一、Object.defineProperty

1、Object.defineProperty是一个用于定义或修改对象属性的方法,可以精确地控制属性的行为,例如可写性、可枚举性和可配置性。

2、在Object.defineProperty 方法中,有三个必需的参数和一个可选的第四参数

  1. obj (必需):要定义属性的对象。可以是任何 JavaScript 对象。
  2. prop (必需):要定义或修改的属性的名称。可以是一个字符串,表示属性的名称。
  3. descriptor (必需):一个对象,用于定义或修改属性的特性。

还可以包含以下可选的属性

- configurable (可选):布尔值,表示该属性是否可以被删除或修改特性。默认为 false。

- enumerable (可选):布尔值,表示该属性是否可以在 for...in 循环中被枚举。默认为 false。

- value (可选):任意类型的值,表示属性的初始值。默认为 undefined。

- writable (可选):布尔值,表示该属性的值是否可以被修改。默认为 false。

- get (可选):函数,表示获取属性值时要调用的函数。

- set (可选):函数,表示设置属性值时要调用的函数。

3、使用实例

  const obj = {    name: "小明", age: 18    }或者const obj = {    }这里不能使用const,const定义的是常量,无法修改;let demoBute= obj.name;使用 Object.defineProperty 定义属性名为 name 的属性Object.defineProperty(obj, "name", {可枚举属性,可以在 for...in 循环中被枚举enumerable: true,可配置属性,可以使用 delete 运算符删除属性configurable: true,获取属性值的函数get: function () {console.log("获取,收集依赖");return demoBute},设置属性值的函数set: function (value) {console.log("更新,通知用户");demoBute = value;}})修改,触发set函数obj.name = "小红"控制台输出:更新,通知用户调用,出发get函数console.log(obj.name);控制台输出:获取,收集依赖小明多次调用,看下运行顺序,按照调用顺序依次执行(set > get > log)只要调用obj都会触发依赖函数obj.name = "小红";             //set >console.log(obj.name);         //get > log控制台输出: 更新,通知用户获取,收集依赖小红

4、get和set

  •  get 函数的作用是在访问属性值时被调用,它不接受任何参数,但需要返回属性的值。在示例中,我们通过return demoBute返回了name的属性值 。
  • set 函数的作用是在设置属性值时被调用,它接受一个参数 value,该参数表示要设置的属性值。在示例中,我们直接把修改后的值value 赋值给demoBute,实现更新。

5、注意事项:get 函数和set 函数,不会同时被触发,它们根据属性的读取或设置操作来决定调用哪个函数。(按照调用顺序从上到下依次执行,就是有更新就只运行set函数,没更新,就只运行get函数)

二、Proxy

1、Proxy方法是一个允许您拦截并自定义对象的底层操作。通过使用Proxy,您可以拦截对象的各种操作,如属性访问、属性赋值、函数调用等,并在这些操作发生时执行自定义行为。

2、基本语法如下,target 是您要代理的目标对象, handler 是一个包含各种拦截操作的对象。 handler 对象中的每个属性都是一个特殊的拦截器,用于拦截不同的操作。

const target = {...... }const handler = {...... }​​​​​​​const proxy = new Proxy(target, handler);

下面是一些常用的拦截器和它们的作用:

1. get(target, property, receiver):拦截属性的读取操作。2. set(target, property, value, receiver):拦截属性的

3、在ES6的Proxy中,get和set是两个常用的拦截器函数,用于拦截对象属性的读取和赋值操作。下面详细介绍这两个函数的用法和功能:

(1)、get(target , property , receiver)

- target :目标对象,即被代理的对象。

- property :要访问的属性名。

- receiver:最初被调用的对象,通常是代理对象或继承代理对象的对象。 - 返回值:返回属性的值。

get 函数在访问目标对象的属性时触发,可以用来拦截属性的读取操作。您可以在 get 函数内部添加自定义的逻辑,例如记录日志、验证访问权限等。下面是一个示例:

const target = {name: "Bob",age: 18
};
const handler = {get(target, property, receiver) {console.log(`正在读取属性:${property}`);return target[property];}
};
const proxy = new Proxy(target, handler);
console.log(proxy.name); // 输出:正在读取属性:name,Bob
console.log(proxy.age); // 输出:正在读取属性:age,18

这里我们创建了一个代理对象 proxy ,当访问 proxy 的属性时, get 函数会被触发,并打印相应的日志信息。

(2)、set(target , property , value , receiver) 

- target :目标对象,即被代理的对象。

- property :要设置的属性名。

- value :要设置的属性值。

- receiver:最初被调用的对象,通常是代理对象或继承代理对象的对象。 - 返回值:返回一个布尔值,表示属性是否设置成功。​​​​​​​

set 函数在给目标对象的属性赋值时触发,可以用来拦截属性的赋值操作。您可以在 set 函数内部添加自定义的逻辑,例如验证赋值的合法性、记录日志等。下面是一个示例:

const target = {name: "Carl",age: 20
};
const handler = {set(target, property, value, receiver) {console.log(`正在设置属性:${property},新值为:${value}`);target[property] = value;return true;}
};
const proxy = new Proxy(target, handler);
proxy.age = 30; // 输出:正在设置属性:age,新值为:30
console.log(proxy.age); // 输出:30

在这里,我们给proxy的age属性赋值时,set函数会被触发,并打印相应的日志信息;通过get 和 set 拦截器函数,您可以在读取和赋值属性时执行自定义的行为,从而实现更灵活和可控的对象操作。

(3)、get和set完整实例​​​​​

const target = {name: "Alice",age: 25
};const handler = {get(target, property, receiver) {console.log(`正在读取属性:${property}`);return target[property];},set(target, property, value, receiver) {console.log(`正在设置属性:${property},新值为:${value}`);target[property] = value;return true;}
};const proxy = new Proxy(target, handler);console.log(proxy.name);     // 输出:正在读取属性:name,Alice
proxy.age = 30;             // 输出:正在设置属性:age,新值为:30
console.log(proxy.age);     // 输出:正在读取属性:age,30

4、handler拦截器的其它参数

  •  get(target, property, receiver):拦截属性的读取操作。
  •  set(target, property, value, receiver):拦截属性的赋值操作。
  •  apply(target, thisArg, argumentsList):拦截函数的调用操作。
  •  has(target, property):拦截in操作符的操作。
  •  deleteProperty(target, property):拦截属性的删除操作
  •  ......

http://www.ppmy.cn/news/823089.html

相关文章

windows下iPad插上电脑iTunes没反应

判断是驱动没安装 首先打开设备管理器查看是否安装了苹果驱动 windowsr命令框输入 devmgmt.msc 查看有没有“苹果移动设备USB驱动”选项,如果没有就安装,有的话就自己百度去,绝对有教程了。 在这下载这个驱动并解压 链接: https://pan.b…

打印机经常没反应的一个解决办法

首先我使用的是网络打印机D-LINK DP-301U1 最近打印机总是无缘无故的不好用,常常是不能打印,重启OK,反复无常。检查了好几次都没有找到问题 今天偶尔看一下监控日志 2010-11-18 10:14:15 用户IP改变 MAC:00:22:B0:6A:47:AE 原IP&a…

自然语言处理从入门到应用——LangChain:代理(Agents)-[基础知识]

分类目录:《自然语言处理从入门到应用》总目录 有些应用程序不仅需要预先确定的LLM或其他工具调用链,而且可能需要根据用户输入的不同而产生不同的链条。在这些类型的链条中,有一个“代理”可以访问一套工具。根据用户输入,代理可…

电脑连打印机不打印,是怎么回事?

打印机打印不出来的问题还是有很多原因的。 想知道是什么原因造成的,要一步一步查。 本文是uu诊所为大家带来的如何解决打印机正常但无法打印的教程。 (1)检查打印机的连接电缆是否插好,如打印机的电源线和数据线; (2)检查打印机是否已经打…

黑暗幽灵(DCM)木马详细分析

腾讯电脑管家 2016/04/13 9:14 0x00 背景 只要插上网线或连上WIFI,无需任何操作,不一会儿电脑就被木马感染了,这可能吗?近期,腾讯反病毒实验室拦截到一个“黑暗幽灵”木马的新变种,该木马功能强大&#xf…

0305kali linux配置运行-docker-macos aarm64

文章目录 1 下载运行2 配置2.1 配置系统环境2.2 配置SSH服务2.3 安装工具 3 问题总结结语 1 下载运行 拉取kali linux镜像 docker pull kalilinux/kali-rolling该镜像为“纯净版”系统,没有任何工具,体积小。下面当我们运行起来之后,到容器中…

c++编写消消乐游戏

#include <SFML/Graphics.hpp> #include <SFML/Audio.hpp> #include <time.h> using namespace sf;#define GAME_ROWS_COUNT 8 #define GAME_COLS_COUNT 8int ts 57; // 每一个游戏小方块区域的大小bool isMoving false; bool isSwap false;// 相邻位置…

ModaHub魔搭社区:AI原生云向量数据库Zilliz Cloud与 OpenAI 集成搭建相似性搜索系统

目录 准备工作 检索图书 本文将讨论如何使用 OpenAI 的 Embedding API 与 Zilliz Cloud 搭建相似性搜索系统。 在本篇中你将看到如何使用 OpenAI 的 Embedding API 和 Zilliz Cloud 完成图书检索。当前,很多的图书检索方案,包括公共图书馆里使用的那些方案,都是使用关键词…