vue雙向綁定原理 請示整體來說 就是爲data的中的每一個屬性字段添加一個getter/seter屬性 以此來追蹤數據的變化,而執行這部操做,依賴的就是js的Object.defineProperty方法Object.defineProperty
是 ES5 中一個沒法 shim 的特性,這也就是 Vue 不支持 IE8 以及更低版本瀏覽器的緣由。vue
下面就來介紹一下Object.defineproperty()瀏覽器
Object.defineProperty 須要三個參數(object , propName , descriptor)spa
1 object 對象 => 給誰加
2 propName 屬性名 => 要加的屬性的名字 【類型:String】
3 descriptor 屬性描述 => 加的這個屬性有什麼樣的特性【類型:Object】雙向綁定
它一共有如下六個個特性code
首先來介紹第一個 value對象
let a = {}; Object.defineProperty(a,'name',{ value:"你好" }) console.log(a); //打印結果 {name: "你好"}
//若是a中自己擁有一個name屬性使用Object.defineproperty去從新定義又會怎樣呢
let a = {
name:'初始值'
};
Object.defineProperty(a,'name',{ value:"你好" }) console.log(a);
//打印結果 {name: "你好"}
這個方法是爲 當前的對象添加一個屬性 而屬性的值爲 ‘你好’,若是對象本來便有這個屬性那麼重寫此屬性 值得一提的是用這種方法定一的屬性時只能讀取不能更改的blog
a.name='我要從新給你賦值'; //以上代碼將會報錯 Error in created hook: "TypeError: Cannot assign to read only property 'name' of object '#<Object>'"
爲何,其緣由就是應爲沒有定義writable特性ip
第二個 writableget
let a = {}; Object.defineProperty(a,'name',{ value:"你好", writable:true }) a.name="我要從新給你賦值"; console.log(a); //打印結果 {name: "我要從新給你賦值"}
此特性是代表 name屬性是否能夠寫入同步
第三個enumerable
此屬性的代表 被定義的屬性是否能夠能夠被for-in循環或Object.keys()檢索到
let a = {}; Object.defineProperty(a, "name", { writable: true, enumerable: true, value:'nihao' }); console.log(Object.values(a));// 打印值["nihao"] let a = {}; Object.defineProperty(a, "name", { writable: true, enumerable: false, value:'nihao' }); console.log(Object.values(a));//打印值[] 定義的屬性name沒有被檢索到
第四個 configurable
此屬性代表是否能夠再次修改 特性
let a = { a_attr:"11" }; Object.defineProperty(a, "name", { writable: false,//定義特性以後 value: "nihao", configurable:false //不容許修改特性 }); Object.defineProperty(a, "name", { value: "nihao", writable:true //將容許寫入特性設置爲true }); a.name="180" //寫入值 報錯Error in created hook: "TypeError: Cannot redefine property: name" console.log(a.name)
第五個 get set
這個就是vue雙向綁定原理的實現基礎了這兩個屬性代表 屬性被寫入或者讀取是執行方法而且是同步的
let a = {}; Object.defineProperty(a, "name", { get(){ console.log("我要被讀取了") return '返回的讀取的值' }, set(val){ console.log("我要被寫入了 我是寫入的值:"+val) } }); console.log(a.name); //執行get方法 打印(我要被讀取了) 和 (返回讀取到的值) a.name="我要寫入你" //執行set方法 打印(我要被寫入了 我是寫入的值:我要寫入你)