Vue数据监听Object.definedProperty()方法的实现

Object.definedProperty()

1. 基本方法

let book = {};
Object.definedProperty(book, 'name', {
	value: 'John',
	writable: false,
	configurable: false,
	enumerable: false,
	get() {
		return newValue;
	},
	set(newValue) {
		book.name = newValue;
	},
});

2. 属性作用

  • value:为当前设定的对象book的属性name的值,此处也可以设定默认值。
    如果不设定默认为undefined

  • writable:能否修改对象book的属性name的值。

    • true: 代表当前的值可通过赋值的方式(见下文)属性重定义的方式(见下文)的方式可进行修改
    • false: 和 true 的情况相反,也就是不能修改对象的属性的值
  • configurable:表示当前对象的属性能否被删除。

    • true: 可以删除对象的属性
    • false: 不能删除对象的属性
  • enumerable: 定义道德对象的属性是否可以在 for...in 循环和 Object.keys() 中进行遍历。

  • (1) value 属性

let person = {};
//  赋值的方式
person.name = 'rose';

//  属性重定义的方式
Object.defineProperty(person, 'name', {
	value: 'jack',
});
  • (2) writable 属性
// 情况一:writable: false
let person = {};
Object.defineProperty(person, 'name', {
	value: 'jack',
	writable: false,
});
person.name = 'rose';
console.log('赋值方式person.name', person.name); //  jack
Object.defineProperty(person, 'name', {
	value: 'jack',
	writable: false,
});
console.log('属性重定义方式person.name', person.name); //  jack

// 情况二:writable: true
let person = {};
Object.defineProperty(person, 'name', {
	value: 'jack',
	writable: true,
});
person.name = 'rose';
console.log('赋值方式person.name', person.name); //  rose
Object.defineProperty(person, 'name', {
	value: 'john',
});
console.log('属性重定义方式person.name', person.name); //  john
  • (3)configurable 属性
// 情况一:configurable: false
let person = {};
Object.defineProperty(person, 'name', {
	value: 'jack',
	configurable: false,
});
delete person.name;
console.log('person', person); // person {name: jack}

// 情况二:configurable: true
let person = {};
Object.defineProperty(person, 'name', {
	value: 'jack',
	configurable: true,
});
delete person.name;
console.log('person', person); // person {}
  • (4) enumerable 属性
let person = {};
Object.defineProperty(person, 'name', {
	value: 'jack',
	enumerable: true,
});
person.gender = 'man';
Object.defineProperty(person, 'age', {
	value: '26',
	enumerable: false,
});
console.log(Object.keys(person)); // [0:'name',1:'gender']
for (const key in person) {
	console.log(key);
} // name gender
  • (5) get()方法

    • 属性的 getter 函数,如果没有 getter ,则为 undefined。 当访问改属性时,会调用此函数,
      执行时不需要传入任何参数,但是默认会传入 this 对象(由于继承关系,这里的 this 指向的 this
      指向不一定是定义改属性的对象)。该函数的返回值会被用作该属性的值。
  • (6) set() 方法

    • 属性的 setter 函数,如果没有 setter ,则为 undefined。当属性值被修改时,会调用此函数。该
      方法接受一个参数(也就是被赋予的新值),会传入赋值的 this 对象。

3. 原理实现

  • 在 MVVM 框架中,一是监听数据的变化,二是数据驱动。

  • 在通常使用中我们使用 Object.definedProperty() 来实现监听数据的变化,或者使用 Proxy 和 反射。

  • 本章通过使用 MutationObserver 来实现 Object.definedProperty() 对数据变化的监听。

  • (1) API 的使用

    • 定义:MutationObserver 构造函数对 DOM 树所做的更改提供了监听的能力。替代了旧的 MutaionEvents
      功能。
    • 返回值:MutationObserver 创建后并返回一个 new MutationObserver,当 DOM 发生改变时,会调用
      制定的回调函数。
    • 注意点:
      • MutationObserver API 是异步触发的,DOM 的改变并不会马上触发,而是等到所有对 DOM 改变的操作
        完成后,整体的触发一次。
      • 面对多次的 DOM 修改,MutationObserver 会将多次的改变记录封装成一个数组进行处理,而不是一条
        一条进行处理。
      • MutationObserver 在不影响浏览器性能的情况下响应 DOM 的更改。
    • 基本方法:
      • disconnect():停止 MutationObserver 的监听,直到再次 observe() 再次被调用。
      • observe():开始监听,并通过回调函数让 MutationObserver 接受通知。
      • takeRecords():从 MutationObserver 的通知队列中移除所有挂起的通知,并在一个新Array
        MutationObserver 对象中返回它们。
  • (2) 代码实现

DOCTYPE html>
<html lang="en">
	<head>
		<meta charset="UTF-8" />
		<meta http-equiv="X-UA-Compatible" content="IE=edge" />
		<meta name="viewport" content="width=device-width, initial-scale=1.0" />
		<title>Object.definedProperty的实现title>
	head>
	<body>
		<div id="app">
			<h1 id="h">h1>
		div>
	body>
html>
<script>
	// 选择要观察的节点
	const targetNode = document.getElementById('app');
	// 具体要观察节点那些改变
	const config = { attributes: true, childList: true, subtree: true };
	// 创建一个回调函数的实例,节点发生改变时执行的回调函数
	const Observer = new MutationObserver((mutationList, observer) => {
		mutationList.forEach((item, index) => {
			if (item.type === 'childList') {
				console.log('有节点发生改变,当前节点的内容是:', item.target.innerHTML);
			} else if (item.type === 'attributes') {
				console.log('修改了' + item.attributeName + '属性');
			}
		});
	});
	// 开始观察节点是否发生变化
	Observer.observe(targetNode, config);
	// 停止观察
	// observer.disconnect();
script>
  • (3) 输出结果
    Vue数据监听Object.definedProperty()方法的实现_第1张图片

你可能感兴趣的:(vue.js,javascript,前端,js,es6)