Vue响应式原理Object.defineProperty这样理解(一)

<div id="app">
    {{message}}
    {{message}}
    {{message}}
</div>
<script src="js/vue.js"></script>
<script>
    const app = new Vue({
        el:'#app',
        data: {
            message: 'O(∩_∩)O哈哈~'
        }
    })
</script>

在这里插入图片描述
我们app.message修改message信息:
在这里插入图片描述
页面上message内容改为:
在这里插入图片描述

1.app.message修改数据,Vue内部是如何监听message数据的变化?

Object.defineProperty->监听对象属性的改变
将data对象传入Vue里

<script>
 const obj = {
        message: 'O(∩_∩)O哈哈~',
        name: 'smy'
    }
    //1.取出obj中所有的key进行遍历
    Object.keys(obj).forEach(key =>{
        //拿到遍历的值
        let value = obj[key]      

拿到值后,接下来我们监听值的改变
原来的message和name不好监听,所以我们把他们原来的属性全部重新定义一下,这里就用到了Object.defineProperty

        Object.defineProperty(obj, key, {
            set(newValue) {
                console.log('监听' + key + '改变');
                value = newValue
            },
            get() {
                console.log('获取' + key + '对应的值');
                return value
            }
        })
    })
    obj.name = 'yyqx'
</script>

(上面是一个完整的代码,方便解释每段代码,我才分开写的)
在这里插入图片描述
如果我们obj.name = 'yyqx'修改name的值,我们要告诉谁我们把这个值修改了呢?

  • 谁用告诉谁,谁在用了
  • 张三李四王五都在用,我们怎么知道谁在用?
  • 那么我们就需要对div中的内容做解析,
  • 根据解析HTML代码,获取到哪些人有用属性,而且这些人在用message的时候会用到message的属性get,
  • 谁用一次,谁就会调用一次Object.defineProperty下面这个get
  • get()中:张三get,李四get,王五get
  • 一旦上面newValue发生改变我们就通知一下这三个人,也就是发布订阅者模式,让这三个人订阅newValue的改变
<body>
<div id="app">
    {{message}}<!--张三用了-->
    {{message}}<!--李四用了-->
    {{message}}<!--王五用了-->
    {{name}}
</div>
<script src="js/vue.js"></script>
<script>
    const obj = {
        message: 'O(∩_∩)O哈哈~',
        name: 'smy'
    }
    Object.keys(obj).forEach(key =>{
        let value = obj[key]
        Object.defineProperty(obj, key, {
            set(newValue) {
                console.log('监听' + key + '改变');
                value = newValue
            },
            get() {
                console.log('获取' + key + '对应的值');
                return value
            }
        })
    })

2.当数据发生改变,Vue如何知道通知哪些人,界面发生刷新?

发布订阅者模式
当通知到这三个人数据变化了,他们还要自己update一下更新界面,也就出现了在Watcher类中update一下,我们把修改好的name加入到Dep中去之后dep.notify()通知订阅者,在Dep发布者中遍历通知订阅者更新界面

//发布者, Dep用来存储所有对属性有依赖的东西
    class Dep {
        constructor() {
            //数组中记录谁要订阅我这个属性
            this.subs = []//subscribe
        }
		//添加watch对象,一旦调用的函数加进来,就把watcher加进来
		//也就进行下面的const w1 = new Watcher('张三'); dep.addSub(w1)操作
        addSub(watcher) {
            this.subs.push(watcher)
        }
        //通知
        notify() {
            this.subs.forEach(item => {
                item.update()
            })
        }
    }

    //监听观察(订阅者)
    class Watcher {
        constructor(name) {
            this.name = name;
        }

        update() {
            console.log(this.name + '发生update');
        }
    }

    const dep = new Dep()
    const w1 = new Watcher('张三')//张三用了一次,这个就在get中
    dep.addSub(w1)//把这个w1加入到dep中去
    dep.notify()//通知订阅者
</script>

(上面是一个完整的代码,方便解释每段代码,我才分开写的)
过程图解:
在这里插入图片描述
将上面的案例套入这个过程图解中
在这里插入图片描述

(资料参考来源微博’coderwhy‘,感谢王红元老师💪)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值