Vue中如何实现响应式的?v-model实现原理?

  用过vue的都知道,vue中data中定义的数据会随着我们通过方法改变该数据的同时,页面上相关此数据的也会相应的刷新,实现响应式数据。它是如何实现这一功能的?

Vue2.xx版本中用Object.defineProperty(obj, prop, descriptor) 

  可传入三个值,其作用是该方法会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性,并返回此对象。

    第一个值传入要修改的对象
    第二个值传入该对象中要修改的key
    第三个值是一个对象,里面有set 和get两种方法 set为值发生修改是所做的操作 get为读取改值时的操作。

  简单实现的代码如下:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <script src="../js/vue.js"></script>
</head>
<body>
  <input type="text">
  <p></p>
  <script>
  var obj = {}
  var temp = null
  document.querySelector('input').oninput =function(){
    //当我们设置obj中的a属性的值时,会触发set方法,接收到新的值,我们将文本框中的值赋给a属性
    obj.a = this.value     
//当我们获取obj中的a属性的值时,会触发get方法,返回新的值,我们将获取到的新值显示在网页的p标签中
    document.querySelector('p).innerHTML = obj.a   }   Object.defineProperty(obj,
'a',{     get:function(){
      console.log('获取到新值在p标签中显示')       
return temp     },     set:function(val){       temp = val
      console.log('监听到了a属性的值在改变')     }   })
</script> </body> </html>

Vue3.xx版本利用ES6中的Proxy

  Vue2.xx版本中的数据双向绑定有如下缺点:

    1. 监听数组的方法不能触发Object.defineProperty方法中的set操作(如果要监听的到话,需要重新编写数组的方法)。

    2. 必须遍历每个对象的每个属性,如果对象嵌套很深的话,需要使用递归调用。Proxy更好的解决如上面的问题。

  当外界每次对obj进行操作时,就会执行handler对象上的一些方法。

  handler中常用的对象方法如下:

    1. get(target, propKey, receiver)

      该方法的含义是:用于拦截某个属性的读取操作。它有三个参数,如下解析:

      target: 目标对象

      propKey: 目标对象的属性

      receiver: (可选),该参数为上下文this对象

    2. set(target, propKey, value, receiver)

      该方法是用来拦截某个属性的赋值操作,它可以接受四个参数,参数解析分别如下:

      target: 目标对象

      propKey: 目标对象的属性名

      value: 属性值

      receiver(可选): 一般情况下是Proxy实列

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
  <input type="text">
  <p></p>
</body>
<script>
var target={
  msg:null
}
document.querySelector('input').oninput=function(){
  obj.msg=this.value
  document.querySelector('p').innerHTML=obj.msg
}
var handler={
  get:function(target,property){
    return target[property];
  },
  set:function(target,property,value){
    target[property]= value
  }
}
var obj=new Proxy(target,handler)
</script>
</html>

 

posted @ 2021-01-03 18:12  腓腓无忧  阅读(144)  评论(0编辑  收藏  举报