vue数据驱动的核心原理及其代码实现
1. vue数据驱动原理图:
2. 简述数据驱动
vuejs在实例化的过程中,会对实例化对象选项中的data 选项进行遍历,遍历其所有属性并使用Object.defineProperty 把这些属性全部转为 getter/setter。
同时每一个实例对象都有一个watcher实例对象,他会在模板编译的过程中,用getter去访问data的属性,watcher此时就会把用到的data属性记为依赖,这样就建立了视图与数据之间的联系。
当之后我们渲染视图的数据依赖发生改变(即数据的setter被调用)的时候,watcher会对比前后两个的数值是否发生变化,然后确定是否通知视图进行重新渲染这样就实现了所谓的数据对于视图的驱动。
通俗地讲,它意味着我们在普通 HTML 模板中使用特殊的语法将 DOM “绑定”到底层数据。
一旦创建了绑定,DOM 将与数据保持同步。每当修改了数据,DOM 便相应地更新。这样我们应用中的逻辑就几乎都是直接修改数据了,不必与 DOM 更新搅在一起。这让我们的代码更容易撰写、理解与维护。
3. MVVM框架的简单描述:
Model:指的是数据部分,对应到前端相当于javascript对象
View:指的是视图部分,对应前端相当于dom
Viewmodel:就是连接视图与数据的中间件通讯
4. 简述 getter/setter :
data对象里的属性,它的每个属性都有两个相对应的get和set方法,顾名思义,get为取值,set为赋值,正常情况下,我们取值和赋值是用obj.prop的方式,但是这样做有一个问题,我如何知道对象的值改变了?
所以就轮到set登场了。你可以把get和set理解为function,当我们调用对象的属性时,我们会进入到get.属性(){...}中,先判断对象是否有这个属性,如果没有,那麽就添加一个name属性,并给它赋值;
如果有name属性,那就返回name属性。你可以把get看成一个取值的函数,函数的返回值就是它拿到的值。
感觉比较重要的是set属性,当给实例赋值:此时,会进入set name(val){...};形参val就是我赋给name属性的值,在这个函数里,就可以做很多事了,比如双向绑定!
因为这个值的每次改变都必须经过set,其他方式是改变不了它的,相当于一个万能的监听器。ES5的对象原型有两个新的属性__defineGetter__和__defineSetter__,专门用来给对象绑定get和set。建议使用下面这种方式,因为是在原型上书写,所以可以继承和重用。
5. Object.defineProperty(obj, prop, descriptor):
(1)定义:方法会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性, 并返回这个对象。
(2)参数:
obj : 要在其上定义属性的对象;
prop: 要定义或修改的属性的名称;
descriptor: 将被定义或修改的属性描述符
(3)属性描述符: (核心)
5-3-1. 定义:对象里目前存在的属性描述符有两种主要形式:数据描述符和存取描述符。数据描述符是一个具有值的属性,该值可能是可写的,也可能不是可写的。存取描述符是由getter-setter函数对描述的属性。描述符必须是这两种形式之一;不能同时是两者。
(4)存取描述符:
5-4-1. get : 一个给属性提供 getter 的方法,如果没有 getter 则为 undefined。当访问该属性时,该方法会被执行,方法执行时没有参数传入,但是会传入this对象(由于继承关系,这里的this并不一定是定义该属性的对象)。
5-4-2. set : 一个给属性提供 setter 的方法,如果没有 setter 则为 undefined。当属性值修改时,触发执行该方法。该方法将接受唯一参数,即该属性新的参数值。
5-4-3. get和set的使用:
var o = {}; // 创建一个新对象
// 在对象中添加一个属性与数据描述符的示例
Object.defineProperty(o, "a", {
value : 37,
writable : true,
enumerable : true,
configurable : true
});
// 对象o拥有了属性a,值为37
console.log(o); //{a: 37}
// 在对象中添加一个属性与存取描述符的示例
var bValue;
Object.defineProperty(o, "b", {
get : function(){
return bValue;
},
set : function(newValue){
bValue = newValue;
console.log(o); //{a: 37,b: 38}
},
enumerable : true,
configurable : true
});
o.b = 38;
// 对象o拥有了属性b,值为38
console.log(o); //{a: 37,b: 38}
// o.b的值现在总是与bValue相同,除非重新定义o.b
6. 基于get和set的简单数据驱动案例实现:
~function(){
var thisChild = {
name: '小明',
age: 12,
sex: 'boy',
class: '7年级2班'
};
var thatChild = {};
observer(thisChild,thatChild);
function observer(data,newData){
//console.log(Object.keys(data))
Object.keys(data).forEach((key)=>{
Object.defineProperty(newData,key,{
get: ()=>{
console.log('得到了:'+v);
return data[key];
},
set: (v)=>{
data[key] = v;
console.log('设置了:'+v);
},
enumerable : true,
configurable : true
})
})
};
thatChild.name = 'daadas';
$('.btn-submit').click(function(e){
var val = $('#name').val();
if(!val) return;
thatChild.name = val;
//console.log(thisChild);
});
}()
6-1. HTML结构:
<form role="form">
<div class="form-group">
<label for="name">姓名</label>
<input type="text" class="form-control" id="name"
placeholder="请输入名称">
</div>
<button type="button" class="btn btn-default btn-submit">提交</button>
</form>
6-2.打印结果:
7. 数据驱动源码实现:(vue)
参考: http://www.cnblogs.com/caizhenbo/p/6710174.html
致自己: 积硅步,行千里 ~
推荐阅读
-
Angular和Vue双向数据绑定的实现原理(重点是vue的双向绑定)
-
vue中子组件向父组件传递数据的实例代码(实现加减功能)
-
Vue 2.0的数据依赖实现原理代码简析
-
Vue组件内部实现一个双向数据绑定的实例代码
-
浅谈vue中数据双向绑定的实现原理
-
利用Object.defineProperty简单实现vue的数据响应式原理
-
Vue、angular等框架实现双向绑定的原理,核心机制是使用了Object.defineProperty
-
【Vue高级】MVVM实现原理(六)—— 双向数据绑定的实现
-
VUE - vue2.0与vue3.0双向数据绑定的实现原理及区别
-
Vue中实现数据双向绑定的原理——Object.defineProperty()