文章參考
阮一峰:MVC,MVP 和 MVVM 的圖示
深入響應式原理
最近工作中一直在使用Vue這一款框架作為開發工具,但是用了之后發現自身對于MVVM的概念并不了解。所以寫下這篇博客作為鞏固基礎知識。
什么是MVVM?
- 概念介紹
- MVVM分為三個部分:分別是M(Model,模型層 ),V(View,視圖層),VM(ViewModel,V與M連接的橋梁,也可以看作為控制器)
1、 M:模型層,主要負責業務數據相關;
2、 V:視圖層,顧名思義,負責視圖相關,細分下來就是html+css層;
3、 VM:V與M溝通的橋梁,負責監聽M或者V的修改,是實現MVVM雙向綁定的要點; - MVVM支持雙向綁定,意思就是當M層數據進行修改時,VM層會監測到變化,并且通知V層進行相應的修改,反之修改V層則會通知M層數據進行修改,以此也實現了視圖與模型層的相互解耦;
- MVVM分為三個部分:分別是M(Model,模型層 ),V(View,視圖層),VM(ViewModel,V與M連接的橋梁,也可以看作為控制器)
-
關系圖
image.png
關于Object.defineProperty
- 介紹
Object.defineProperty
可以再一個對象中定義或者修改一個屬性,然后返回這個對象,并且可對該屬性的可寫行,可便利性,存取描述符(get、set)等進行設定; - 參數
Object.defineProperty(obj, prop, descriptor)
;- obj: 需要進行定義或修改屬性的對象;
- prop: 需要進行定義或者修改的屬性;
- descriptor: 該屬性的描述符(包含存取描述符和數據描述符),該參數以一個對象的形式傳入,該參數有六個選項:
- value: 設定該屬性的值;
- writable: 布爾,該屬性是否可寫入(是否可改變其value);
- enumerable: 布爾,該屬性是否可被遍歷得到(for...in, Object.keys等);
- configurable: 布爾,設定該屬性是否可被刪除,且除writable外的其他描述符是否可被修改;
- get: 函數,該屬性的值被獲取時執行的回調函數(例如console.log(prop)),默認為undefined;
- set: 函數,該屬性的值被設置時執行的回調函數,默認為undefined;
- 簡單例子
// 沒有get和set
let obj = {
}
Object.defineProperty(obj, 'a', {
value: 123, // 該屬性值為123
enumerable: false, // 不可被遍歷得到
writable: false, // 不可被重新寫入
configurable: false // 不可被刪除,且enumerable和value不能通過Object.defineProperty重新定義
})
// 使用get和set
let obj = {
// 設定默認值
_data: {
a: 123
}
}
Object.defineProperty(obj, 'a', {
get() {
// 當獲取a時執行
console.log('a被獲取了')
return obj._data.a
},
set(value) {
// 當修改a時執行
obj._data.a = value
console.log('a的值被修改了')
}
})
- 數據描述符和存取描述符
在descriptor
的六個選項中,有數據描述符和屬性描述符,他們是不可共存的,否則會報錯(因為功能上有所重復和沖突),其中- 數據描述符:value,writable;
- 存取描述符:get,set;
- 兩者皆可共存:configurable,enumerable;
- 報錯例子
let obj = {
}
Object.defineProperty(obj, 'a', {
value: 123,
get() {
// 當獲取a時執行
console.log('a被獲取了')
return obj._data.a
},
set(value) {
// 當修改a時執行
obj._data.a = value
console.log('a的值被修改了')
}
})
- 兼容性
至少IE8以上
使用Object.defineProperty實現MVVM的表單數據雙向綁定
- 有這么一個表單和一個
person
對象
- 需要實現的功能(該表單與person對象的雙向綁定)
- 1.用戶在表單中輸入的數據實時綁定在person對象的同名屬性中;
- 2.在person對象中進行屬性的修改會實時反映在表單中;
-
獲取form的DOM節點,并且設置默認值,該默認值在Vue中就是data對象中的數據;
- 實現用戶輸入數據與person對象內同名屬性的同步修改
- 一、用
Object.defineProperty
為person對象設定name和age兩個屬性,并且他們的get獲取的是_data里的數據
-
二、監聽form表單中的input事件,并且將獲取的目標DOM節點的value值賦值給person對象中的響應屬性即可完成用戶輸入與對象值間的綁定
效果圖:
- 一、用
-
實現person對象同名屬性的修改同步用戶表單框中的輸入值
效果圖:修改直接修改person對象中的name和age屬性的值,可以同步顯示在輸入框中
-
這時候其實已經完成了數據的雙向綁定,再做一些小優化
缺點
本身form節點中只有name和age兩個輸入框對應person中的屬性,如果這時候我在form節點中新添加一個輸入框進去,這個新添加的input輸入的值是沒有雙向綁定效果的;
PS:在Vue中,created
函數后新添加的屬性不會進行監聽,因為這時候的數據已經初始化完畢,當然Vue本身也提供了一個Vue.set(object, key, value)
api使其可以在created
后對data對象進行屬性的添加;