Vue如何追踪变化
vue.js采用的是数据劫持结合发布和-订阅者模式的方式,通过Object.defineProperty()来劫持各个属性的setter,getter,在数据变动时发布消息给订阅者,触发相应的监听回调。
当你把一个普通的 JavaScript 对象传给 Vue 实例的 data 选项,Vue 将遍历此对象所有的属性,并使用 Object.defineProperty
(ES5 中一个无法 shim 的特性)把这些属性全部转为 getter/setter
。
这些 getter/setter
对用户来说是不可见的,但是在内部它们让 Vue 追踪依赖,在属性被访问和修改时通知变化。
每个组件实例都有相应的 watcher 实例对象,它会在组件渲染的过程中把属性记录为依赖,之后当依赖项的 setter 被调用时,会通知 watcher 重新计算,从而致使它关联的组件得以更新。
实现
页面结构很简单,如下
<div id="app">
<form>
<input type="text" v-model="number">
<button type="button" v-click="increment">增加</button>
</form>
<h3 v-bind="number"></h3>
</div>
最后会通过类似于vue的方式来使用我们的双向数据绑定,结合我们的数据结构添加注释
模仿vue写法创建一个vue实例
var app = new myVue({
el:'#app',
data: {
number: 0
},
methods: {
increment: function() {
this.number ++;
},
}
})
首先我们需要定义一个myVue构造函数:为了初始化这个构造函数,给它添加一 个_init属性
function myVue(options) {
this._init(options);
}
myVue.prototype._init = function (options) {
this.$options = options; // options 为上面使用时传入的结构体,包括el,data,methods
this.$el = document.querySelector(options.el); // el是 #app, this.$el是id为app的Element元素
this.$data = options.data; // this.$data = {number: 0}
this.$methods = options.methods; // this.$methods = {increment: function(){}}
}
接下来实现_obverse
函数,对data进行处理,重写data的set和get函数,并改造_init函数
首先了解一下es5的Object.defineProperty
的api,
configurable:true | false, //这个就两个意思能不能改属性和能不能删除属性