1. 程式人生 > 實用技巧 >Vue中如何實現響應式的?v-model實現原理?

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>