var watcher = this._watcher = new Watcher( this.vm, this.expression, this._update, // callback { filters: this.filters, twoWay: this.twoWay, deep: this.deep, preProcess: preProcess, postProcess: postProcess, scope: this._scope } ) // v-model with inital inline value need to sync back to // model instead of update to DOM on init. They would // set the afterBind hook to indicate that. if (this.afterBind) { this.afterBind() } else if (this.update) { this.update(watcher.value) } Directive.prototype.set = function (value) { /* istanbul ignore else */ if (this.twoWay) { this._withLock(function () { this._watcher.set(value) }) } else if (process.env.NODE_ENV !== 'production') { warn( 'Directive.set() can only be used inside twoWay' + 'directives.' ) } }
src目录下Watch.js:
从下面的代码可以找到watcher对象通过addDep方法实现订阅
Watcher.prototype.addDep = function (dep) { var id = dep.id if (!this.newDepIds.has(id)) { this.newDepIds.add(id) this.newDeps.push(dep) if (!this.depIds.has(id)) { dep.addSub(this) } } }
2.前面说那么多关于双向绑定,其实这也是VUE内部的渲染机制,总结如下
1. 通过 observer 对 data 进行了监听,并且提供订阅某个数据项的变化的能力
2. 把 template 解析成一段 document fragment,然后解析其中的 directive,得到每一个 directive 所依赖的数据项及其更新方法。比如 v-text="message" 被解析之后 (这里仅作示意,实际程序逻辑会更严谨而复杂):所依赖的数据项this.$data.message,以及相应的视图更新方法 node.textContent = this.$data.message
3. 通过 watcher 把上述两部分结合起来,即把 directive 中的数据依赖订阅在对应数据的 observer 上,这样当数据变化的时候,就会触发 observer,进而触发相关依赖对应的视图更新方法,最后达到模板原本的关联效果。
3.vue是如何改进了v-for具有相同数据渲染出错的?
数组的渲染
未使用track-by的数组渲染内部缓存的默认id是数组的值value,意味着如果数组中存在相同的值,通过id获取的是相同的一个fragement片段,最后通过insertBefore操作DOM由于是相同的一个实例,故不会生效。
<div> <ul> <li>child1</li> <li>child2</li> </ul> </div> <script> _element1=document.getElementById('child1'); _element2=document.getElementById('child2'); document.getElementById('test').insertBefore(_element1,_element2); </script>
渲染的结果是child2在child1前面
使用track-by目的是自定义这个内部的id,使得数组中具有相同的值的几项都不会选择到相同的实例,对于使用track-by='$index'还是其他唯一区分的id值有一定的区别,各有好处。
使用$index使得反转的数据没有移动操作,而对于使用其他的id在顺序不一样的时候会有相应的移动操作。
对象的渲染
对象一般使用键作为内部缓存对象的id,通过track-by也可以自定义这个id提高性能。
vm.model = { a: { id: 1, val: "model1"}, b: { id: 2, val: "model2"}, c: { id: 3, val: "model2"}, }
列表更新
vm.model = { d: { id: 1, val: "model1"}, e: { id: 2, val: "model2"}, f: { id: 3, val: "model2"} }
以上所述是小编给大家介绍的vue从使用到源码实现教程详解,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对脚本之家网站的支持!
您可能感兴趣的文章: