您好,登錄后才能下訂單哦!
這篇文章主要介紹“Vue中的MVVM模式原理是什么”的相關知識,小編通過實際案例向大家展示操作過程,操作方法簡單快捷,實用性強,希望這篇“Vue中的MVVM模式原理是什么”文章能幫助大家解決問題。
傳統的組件是靜態渲染,數據更新需要操作DOM。Vue框架采用了MVVM(Model-View-ViewModel)模式來管理應用程序的數據模型(Model)和視圖界面(View)的交互,即數據驅動視圖,從而避免了操作DOM。
MVVM的基本思想是將模型數據和用戶視圖解耦(Decoupling),即Model和View分離開來,使得它們之間的依賴關系降到最小。然后通過ViewModel來協調它們之間的通信。當Model發生變化時,我們不需要手動更新View,而是可以通過Vue的響應式機制,讓Vue自動更新View。同樣,當用戶與View交互時,我們也不需要手動修改Model,而是可以通過Vue的指令和事件機制,讓Vue自動更新Model。這種解耦機制使得我們可以更加專注于業務邏輯的實現,而不需要過多地關注View和Model之間的細節。
Model:Vue應用程序中的數據模型,通常是一個JavaScript對象或數組。這些數據模型被存儲在Vue實例的data屬性中。
View:Vue應用程序中的視圖界面,通常是由HTML模板和Vue指令組成的。Vue的模板語法允許開發人員在HTML中綁定數據和表達式,以實現動態更新。
ViewModel:ViewModel是Vue應用程序的核心,它是一個Vue實例,它充當Model和View之間的橋梁。ViewModel負責管理數據和行為,它可以將Model數據綁定到View上,同時也可以響應View上的事件和用戶交互。ViewModel中包含了一個Watcher和Directive,它們可以監聽Model數據的變化,并自動更新View。
Vue的響應式機制是指當Vue實例中的數據發生變化時,與之關聯的視圖會自動更新。實現Vue響應式機制需要借助ES5的Object.defineProperty()
方法,使用該方法監聽對象屬性的變化。
Object.defineProperty(obj, prop, descriptor)
用來定義對象的屬性。函數中傳入三個參數,obj
表示要定義屬性的對象,prop
表示要定義的屬性名,descriptor
是一個包含屬性描述符的對象。下面這段代碼是該函數的基本使用:
let data = {}; let name = '小明'; Object.defineProperty(data, "name", { get: function(){ console.log('get') return name }, set: function(newValue){ console.log('set') name = newValue } }) // 測試 console.log(data.name) data.name = '小紅' console.log(data.name)
以下代碼模擬了的監聽對象的過程,當data對象中的數據發生變化時,就會調用updateView()
函數,觸發視圖更新。
// 觸發視圖更新,模擬Model變化后,View發生改變,簡單起見就直接打印一個結果 function updateView(){ console.log('視圖更新') } // 重新定義屬性,實現對數據的監聽 function defineReactive(target, key, value){ // 核心 API Object.defineProperty(target, key, { get(){ return value }, set(newValue){ if(newValue !== value){ value = newValue updateView() } } }) } // 監聽對象屬性 function observer(target){ // 如果監聽的數據類型不是對象,直接返回原數據 if(typeof target !== 'object' || target === null){ return target } // 重新定義對象的每個屬性 for(let key in target){ defineReactive(target, key, target[key]) } } // 數據 let data = { name: '小明', age: 20, info: { address: '北京' } } // 監聽數據 observer(data) // 測試 data.name = '小紅' data.age = 21 data.name // 會觸發getter函數 data.age
假如數據對象中還包含對象,此時就需要進行深度監聽,例如data中的info
數據。只需要在上述的defineReactive()
函數中,再次調用observer()
函數,對傳入的對象的屬性值value
進行監聽。
設置新值時,如果設置的值還是一個對象類型,此時還需要對新值進行監聽。
function updateView(){ console.log('視圖更新') } // 重新定義屬性,實現對數據的監聽 function defineReactive(target, key, value){ // 再次對傳入的對象的屬性值調用監聽函數 observer(value) // 核心 API Object.defineProperty(target, key, { get(){ return value }, set(newValue){ // 對新設置的值進行監聽 observer(newValue) if(newValue !== value){ value = newValue updateView() } } }) } // 監聽對象屬性 function observer(target){ // 如果監聽的數據類型不是對象,直接返回原數據 if(typeof target !== 'object' || target === null){ return target } // 重新定義對象的每個屬性 for(let key in target){ defineReactive(target, key, target[key]) } } // 數據 let data = { name: '小明', age: 20, info: { address: '北京' } } // 監聽數據 observer(data) // 測試 data.name = '小紅' data.age = {num: 21} data.age.num = 22 data.info.address = '上海'
// 觸發更新視圖 function updateView() { console.log('視圖更新') } // // 重新定義數組原型 const oldArrayProperty = Array.prototype // 創建新對象,原型指向 oldArrayProperty ,再擴展新的方法不會影響原型 const arrProto = Object.create(oldArrayProperty); // 對數常用的方法進行擴展 ['push', 'pop', 'shift', 'unshift', 'splice'].forEach(methodName => { arrProto[methodName] = function () { oldArrayProperty[methodName].call(this, ...arguments) updateView() // 觸發視圖更新 Array.prototype[methodName].call(this, ...arguments) } }) // 重新定義屬性,監聽起來 function defineReactive(target, key, value) { // 深度監聽 observer(value) // 核心 API Object.defineProperty(target, key, { get() { return value }, set(newValue) { if (newValue !== value) { // // 深度監聽 observer(newValue) // 設置新值 // 注意,value 一直在閉包中,此處設置完之后,再 get 時也是會獲取最新的值 value = newValue // 觸發更新視圖 updateView() } } }) } // 監聽對象屬性 function observer(target) { if (typeof target !== 'object' || target === null) { // 不是對象或數組 return target } // 修改數組的原型 if (Array.isArray(target)) { target.__proto__ = arrProto } // 重新定義各個屬性(for in 也可以遍歷數組) for (let key in target) { defineReactive(target, key, target[key]) } } // 準備數據 const data = { // name: '小明', // age: 20, // info: { // address: '北京' // 需要深度監聽 // }, nums: [10, 20, 30] } // 監聽數據 observer(data) // 測試 data.nums.push(4) // 監聽數組
深度監聽需要對數據對象遞歸到底,一次性計算量大。
如果數據新增屬性和刪除屬性,則無法監聽到,需要使用 Vue.set()
和 Vue.delete()
方法。
無法原生監聽數組,需要特殊處理。
關于“Vue中的MVVM模式原理是什么”的內容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業相關的知識,可以關注億速云行業資訊頻道,小編每天都會為大家更新不同的知識點。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。