首页 > 其他 > 详细

vue数据双向绑定原理

时间:2020-02-10 00:20:44      阅读:89      评论:0      收藏:0      [点我收藏+]

vue数据双向绑定是通过数据劫持结合发布者-订阅者模式的方式来实现的,那么vue是如果进行数据劫持的,我们可以先来看一下通过控制台输出一个定义在vue初始化数据上的对象是个什么东西。

Object.defineProperty( )是用来做什么的?它可以来控制一个对象属性的一些特有操作,比如读写权、是否可以枚举,这里我们主要先来研究下它对应的两个描述属性get和set,如果还不熟悉其用法,

 

什么是数据响应式?

数据响应式即数据双向绑定,就是把Model绑定到view,当我们通过js修改Model,View会自动更新;若我们更新了View,Model的数据也会自动更新,这就是双向绑定。 

数据响应式原理

vue2.0版本是利用了Object.defineProperty()这个方法重新定义对象获取属性值的get和设置属性值set的操作来实现的。

vue3.0版本采用了Es6的Proxy对象来实现。

我们先分别了解下defineProperty方法、Proxy对象。

什么是defineProperty?

defineProperty简言之,是定义对象的属性。

它其实并不是核心的为一个对象做数据绑定,而是给对象做属性标签。定义对象的属性。只不过是属性的get和set实现了响应式。

它可以来控制一个对象属性的一些特有操作,比如读写权、是否可以枚举,这里我们主要先来研究下它对应的两个描述属性get和set,如果还不熟悉其用法,

属性名 默认值
value undefined
get undefined
set undefined
writable false
enumerable false
configurable false

 

 

 

 

 

 

在平常,我们很容易就可以打印出一个对象的属性数据:

var person = {
  name: ‘小明‘
};
console.log(person.name);  // 小明

如果想要在执行console.log(person.name)的同时,直接给书名加个书名号,那要怎么处理呢?或者说要通过什么监听对象 Book 的属性值。

这时候Object.defineProperty( )就派上用场了,代码如下:

var person = {}
var name = ‘‘;
Object.defineProperty(person, ‘name‘, {
  set: function (value) {
    name = value;
    console.log(‘你取了一个书名叫做‘ + value);
  },
  get: function () {
    return ‘***‘ + name + ‘***‘
  }
})
 
Book.name = ‘vue权威指南‘;  // 你取了一个书名叫做vue权威指南
console.log(Book.name);  // ***vue权威指南***

我们通过Object.defineProperty( )设置了对象Book的name属性,对其get和set进行重写操作。

顾名思义,get就是在读取name属性这个值触发的函数,set就是在设置name属性这个值触发的函数。

所以当执行 Book.name = ‘vue权威指南‘ 这个语句时,控制台会打印出 "你取了一个书名叫做vue权威指南",

紧接着,当读取这个属性时,就会输出 "《vue权威指南》",因为我们在get函数里面对该值做了加工了。如果这个时候我们执行下下面的语句,控制台会输出什么?

console.log(Book);

结果:

技术分享图片

接下来我们通过其原理来实现一个简单版的mvvm双向绑定代码。

 

<div id="app">
      <input v-model="text" id="test"></input>
      <div id="show"></div>
</div>

 

var obj = {
    a:1,
    b:2
};
var _value = obj.a
Object.defineProperty(obj,‘a‘,{
    get:function(){ 
        console.log("get方法")
        return _value
    },
    set:function(newValue){ 
        console.log("set方法")
        _value = newValue
        document.getElementById(‘test‘).value   =_value
        document.getElementById(‘show‘).innerHTML  =_value
        return _value
    }
});
document.getElementById(‘test‘).addEventListener(‘input‘,function(e){
    obj.a = e.target.value;
})

效果如下:

 技术分享图片     技术分享图片

 

 

 

那么,在vue中从一个数据到发生改变的过程是什么?

技术分享图片

 

 

 

注意点:

defineProperty的get、set属性是指对象属性,那数组怎么办? 

监听数组的改变

1)先拷贝一份数组原型链  2)定义一个方法总类

3)遍历数组,给数组原型链重新写方法,然后触发更新 dep.notify

技术分享图片

 

 

 proxy是什么?

https://www.jianshu.com/p/a831f76e5e71

Proxy对象用于定义基本操作的自定义行为,和defineProperty功能类似,只不过用法有些不同

两者比较:

Proxy好处:

1)数据若是多层,去除循环    

2)不需要借助外部的value,不需要设置具体属性

3)不会污染原对象,Proxy只是代理了原对象

var obj = {
    a:1,
    b:2
};
var proxyObj = new Proxy(obj, {
  get(target, key, receiver){ //我们在这里拦截到了数据
        console.log("get方法",target,key,receiver)
        return target[key]
    },
    set(target,key,value, receiver){  //改变数据的值,拦截下来额
        console.log("set方法",target,key,value, receiver)
        return Reflect.set(target,key,value)
    }
})
console.log(proxyObj)

结果如下:

技术分享图片

 

var proxyObj = new Proxy(obj, {
  get:function(target, key, receiver){ //我们在这里拦截到了数据
        console.log("get方法",target,key,receiver)
        return true
    },
    set:function(target,key,value, receiver){  //改变数据的值,拦截下来额
        console.log("set方法",target,key,value, receiver)
        target[key]= value
        document.getElementById(‘test‘).value= value
        document.getElementById(‘show‘).innerHTML=value
        return true
    }
})

document.getElementById(‘test‘).addEventListener(‘input‘,function(e){
  proxyObj.a = e.target.value;
})

 

 

 

为什么vue3中改用proxy

defineProperty只能监听某个属性,不能对全对象监听,所以可以省去for in 提升效率

可以监听数组,不用再去单独对数组做操作

 

vue数据双向绑定原理

原文:https://www.cnblogs.com/renzm0318/p/12289415.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!