VUE响应式原理-如何追踪变化

vue

Vue 最独特的特性之一,是其非侵入性的响应式系统。数据模型仅仅是普通的 JavaScript 对象。而当你修改它们时,视图会进行更新。这使得状态管理非常简单直接

如何追踪变化

当你把一个普通的 JavaScript 对象传入 Vue 实例作为 data 选项,Vue 将遍历此对象所有的 property,并使用 Object.defineProperty 把这些 property 全部转为 getter/setter。Object.defineProperty 是 ES5 中一个无法 shim 的特性,这也就是 Vue 不支持 IE8 以及更低版本浏览器的原因。

这些 getter/setter 对用户来说是不可见的,但是在内部它们让 Vue 能够追踪依赖,在 property 被访问和修改时通知变更。这里需要注意的是不同浏览器在控制台打印数据对象时对 getter/setter 的格式化并不同,所以建议安装 vue-devtools 来获取对检查数据更加友好的用户界面。

每个组件实例都对应一个 watcher 实例,它会在组件渲染的过程中把“接触”过的数据 property 记录为依赖。之后当依赖项的 setter 触发时,会通知 watcher,从而使它关联的组件重新渲染。

<!DOCTYPE html>

<html>

<head>

<meta charset="utf-8">

<title></title>

</head>

<body>

<script type="text/javascript">

let oldArrPrototype = Array.prototype;

// 继承

let proto = Object.create(oldArrPrototype);

['push', 'shift', 'unshift','splice'].forEach(method => {

proto[method] = function() {

// 切片编程

// 更新视图

updateView();

oldArrPrototype[method].call(this, ...arguments)

}

})

// 观察函数

function observer(target) {

if (typeof target !== 'object' || target === null) {

return target;

}

if (Array.isArray(target)) {

target.__proto__ = proto;

// target.constructor.prototype = proto;

}

for (let key in target) {

/*

target:对象本身

key:对象的属性

target[key]:对象的值

*/

definedReactive(target, key, target[key])

}

}

// defineProperty函数

function definedReactive(target, key, value) {

// 重新观察一下传过来的值

observer(value); //递归

Object.defineProperty(target, key, {

// get 读取属性值触发

get() {

return value;

},

// 修改属性值触发,默认有参数,是最新值

set(newValue) {

// 为了方式更改后的值也是对象

observer(newValue);

// 判断新值和旧值是否相同

// 如果不同,改变旧值,更新视图

if (newValue !== value) {

value = newValue;

updateView(value);

} else {

return newValue;

}

}

})

}

// 更新视图方法

function updateView(value) {

console.log("更新视图" + value)

}

// 使用Object.defineProperty可以给属性重新定义属性,给属性增加getter,setter

// 这样给属性增加或者读取属性是都会触发getter 或者 setter

let data = {

name: "oldValue",

onj: {

name: "szx"

},

a: null,

n:[1,2,3]

}

// 定义一个观察函数,只要数据发生变动会触发更新视图的方法

observer(data)

// data.name = "newValue"

// data.a = {

// name: "100"

// },

// data.a.name = 200

data.n.splice(0)

console.log(data)

// 如果属性不存在,即没有事先在data里面定义,赋值不存在的属性值的时候不会触发更新

</script>

</body>

</html>

以上是 VUE响应式原理-如何追踪变化 的全部内容, 来源链接: utcz.com/z/378045.html

回到顶部