Vue.js最显著的一个功能是响应系统--修改Model层的数据,会造成对应View层的更新.这是一个比较方便管理模式,使用户在管理View和Model时变的简单直观.其内部实现是把一个普通对象传给Vue实例作为它的data选项,Vue.js将遍历它的属性,用Object.defineProperty将它们转为getter/setter(这一过程发生在解析阶段),利用这个ES5的特性,Vue实现了数据的双向绑定.
在创建数据绑定时,Vue会建立起一个watcher对象,所以当setter被调用时,就会触发watcher重新计算,导致关联指令更新Dom视图.上面提到的只是Vue对数据双向绑定的大体的实现,至于其中可能碰到的细节问题,就不赘述了.毕竟实现思路和实现细节是两个概念层的东西,有兴趣的同学可以到官网上研究下,这里主要讲解下Object.defineProperty方法.
Object.defineProperty 方法
Object.defineProperty是ECMAScript5.1(ECMA-262)中定义的标准属性,该方法提供了一种直接的方式来定义对象属性或者修改已有对象属性。其方法原型如下:
Object.defineProperty(obj, prop, descriptor)
- obj :目标对象prop ,需要定义的属性或方法的名字。
- descriptor:待修改属性的相关描述descriptor 目标属性所拥有的特性,其默认值如下:
/**
* @{param} descriptor
*/
{
configurable: false,
enumerable: false,
writable: false,
value: null,
set: undefined,
get: undefined
}
- configurable:属性是否可配置。
可配置的含义包括:是否可以删除属性(delete),是否可以修改属性的 writable,enumerable,configurable属性。 - enumerable ,属性是否可枚举。可枚举的含义包括:是否可以通过 for...in 遍历到,是否可以通过 Object.keys() 方法获取属性名称。
- writable ,属性是否可重写。可重写的含义包括:是否可以对属性进行重新赋值。
- value ,属性的默认值。
- set ,设置钩子函数.属性被设置时触发。
- get ,获取钩子函数.属性读取时触发。
以下是一个实现数据和视图绑定的例子:
<div>
<p>你好:<span id='nickName'></span></p>
<p>你想要做什么:<span id="introduce"></span></p> <br/>
<input oninput="setName(this)" placeholder="请输入你的姓名">
<input oninput="setThing(this)" placeholder="输入你要做的是事">
</div>
<script>
//视图控制器
var userInfo = {};
Object.defineProperty(userInfo, "nickName", {
get: function(){
return document.getElementById('nickName').innerHTML;
},
set: function(nick){ document.getElementById('nickName').innerHTML = nick;
}
});
Object.defineProperty(userInfo, "introduce", {
get: function(){
return document.getElementById('introduce').innerHTML;
},
set: function(introduce){ document.getElementById('introduce').innerHTML = introduce; }
});
function setName(e) {
userInfo.nickName = e.value;
}
function setThing(e) {
userInfo.introduce = e.value;
}
</script>
上面代码有很多问题,只为演示相关原理的实现.Vue对这块的实现应该是比较复杂的,但核心方法使用应该相同.下一章我们会深入生存周期和组件方面的研究