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>