当你把一个普通的 JavaScript 对象传入 Vue 实例作为 data 选项,Vue 将遍历此对象所有的属性,并使用 Object.defineProperty 把这些属性全部转为 getter/setter。Object.defineProperty 是 ES5 中一个无法 shim 的特性,这也就是 Vue 不支持 IE8 以及更低版本浏览器的原因。
这些 getter/setter 对用户来说是不可见的,但是在内部它们让 Vue 能够追踪依赖,在属性被访问和修改时通知变更。这里需要注意的是不同浏览器在控制台打印数据对象时对 getter/setter 的格式化并不同,所以建议安装 vue-devtools 来获取对检查数据更加友好的用户界面。
每个组件实例都对应一个 watcher 实例,它会在组件渲染的过程中把“接触”过的数据属性记录为依赖。之后当依赖项的 setter 触发时,会通知 watcher,从而使它关联的组件重新渲染。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<h1>hello world</h1>
<script>
// const data = {
// count: 0
// }
// data.count++
// data.count 什么时候变了?
// 有个API:Object.defineProperty 可以定义对象属性成员的:访问器|修改器
// 说白了就是可以在访问(或者修改)某个对象成员的时候做一些额外的操作
// 也就是我们能监视到对象成员的访问和修改
const data = {}
let _count = 0
Object.defineProperty(data, 'count', {
// value: 10,
// 当你访问该属性的时候,调用 get 方法,
// 属性的值就是 get 方法的返回值
// 注意:get 方法和 value 属性只能有一个
get () {
console.log('get 方法被调用了')
return _count
},
// 当你对属性进行赋值的时候会调用 set 方法
// set 方法接收一个参数:就是你赋的那个数据
set (value) {
console.log('set 方法被调用了', value)
_count = value
document.querySelector('h1').innerText = value
// 发布一个事件:count 数据修改事件
}
})
// data.count = 1此时页面的hello world改为1
</script>
</body>
</html>
Vue响应式原理
最新推荐文章于 2024-07-28 20:26:55 发布