Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
4.0k views
in Technique[技术] by (71.8m points)

vue订阅发布者模式疑问

最近看源码,突然有个问题没相通,求大佬解释一下,
比如我的 data(){retrun{name:"张三"}}
模板里面是有两个div渲染的name 都是

<template>
    <div id="root">
        <div id='name1'>{{name}}<div>
        <div id='name2'>{{name}}<div>
    </div>
</template>

源码里面
/ 通知所有Watcher对象更新视图 /

Dep.prototype.notify = function notify() {
    // stabilize the subscriber list first
    var subs = this.subs.slice();
    for (var i = 0, l = subs.length; i < l; i++) {
        //更新数据
        subs[i].update();
    }
};


**为什么要循环调用watcher.update 既然循环的第一次 已经把name 重新渲染了 循环的第二次 再改变name有什么用?
还是说第一次只改变了上面id 为name1 的div 的视图 不会改变id为name2 的div的视图?**


我理解的发布订阅者模式,每个订阅者收到订阅通知之后都会执行自己的不同的方法, 但是这里的watcher是同一个构造函数创建的 而且执行的update方法都是 最后调用updateComponent 方法来改变视图。
因为我还没有看到源码的后面去这个疑惑让我很难静下心来继续。 求大佬解释一下,还是说我根本没有理解到??


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

你的这个整个template的内容经过vue解析后,就是一个render-watcher,在进行依赖收集的时候,并不会重复收集,详细代码看Watcher.prototype.addDep

Watcher.prototype.addDep = function addDep(dep) {
    var id = dep.id;
    if(!this.newDepIds.has(id)) {
        //为观察者的deps添加依赖dep
        this.newDepIds.add(id);
        this.newDeps.push(dep);
        if(!this.depIds.has(id)) {
            //为dep添加该观察者
            dep.addSub(this);
        }
    }
};

所以当name更改的时候,并不会触发多次渲染。那为什么要循环调用watcher.update,因为它要通知其他的监听者,比如watch里监听name的normal-watcher,比如computed里面使用到name属性的计算属性computed-watcher,还有可能是来自父组件/子组件/兄弟组件等等的watcher


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...