前端練習37 迷你MVVM

2021-09-05 12:50:47 字數 3174 閱讀 1974

如何獲取所有文字節點

definepropertydefineproperties將字串替換為引數變數

如何標記依賴的元素

做乙個小型的mvvm庫,可以做到資料和檢視之間的自動同步。

你需要做的就是完成乙個函式bindviewtodata,它接受乙個dom節點和乙個物件data作為引數。bindviewtodata會分析這個dom節點下的所有文字節點,並且分析其中被}包裹起來的表示式,然後把其中的內容替換成在data上下文執行該表示式的結果。例如:

bindviewtodata

(document.

getelementbyid()

// div 裡面的 p 元素的內容為

// my name is lucy green, i am 13 years old.

'jerry'

16// div 裡面的 p 元素的內容自動變為

// my name is jerry green, i am 16 years old.

當資料改變的時候,會自動地把相應的表示式的內容重新計算並且插入文字節點。

對dom的操作和屬性又有點忘記了,獲取子節點原來都使用的節點的children屬性,但是children裡面並沒有文字節點,要使用的是childnodes屬性。

二者的最主要的區別就是:childnodes會返回文字節點和空節點,而children屬性不會返回文字節點和空節點

所以這裡我們要使用childnodes屬性,並且通過nodename === '#text'篩選文字節點(也可以使用nodetype === 3),然後通過node.data獲取文字

然後通過遞迴篩選出所有的文字節點,這之前練習過的獲取元素標籤《前端練習20 dom標籤統計》是類似的,有幾個方式

複習一下,這裡是將所有文字節點放到乙個陣列中:

可以在遞迴呼叫時多傳遞乙個變數引數來儲存結果:

const getalltextnode = (node, result = ) => 

if (node.childnodes.length > 0)

return result

};

也可以直接遞迴,通過將陣列返回值展平來實現:

const getalltextnode = (node) => 

if (node.childnodes.length > 0)

};

當然也可以通過reduce來實現:

const getalltextnode = (node) => 

if (node.childnodes.length > 0) , ).filter(v => v)

}};

實際使用的時候,不能只返回乙個成員是字串或者是節點的陣列,還需要將節點的初始值存起來,否則的話替換一次之後就沒有辦法響應式的變化了

// 收集依賴

const collectdep = node => }'))

}} if (node.childnodes.length > 0)

};

上面的方法我們返回值是乙個陣列,陣列成員是物件,裡面的origintext就是我們存的表示式初始值

實現響應式,使用了definepropertydata裡面每個屬性的settergetter劫持

注意defineproperty和``definepropertiessetter`方法傳入的引數是不同的,實現的時候又搞混了

// 劫持data的setter,實現響應式更新

const keys = object.keys(data);

if (keys.length > 0) ,

set(newvalue)

})});

}

這個方法和之前練習過的《前端練習28 執行任意表示式》是一樣的,避免使用evalwith,使用new function來實現

// 替換字串為變數

const replacestr = (str, data) => \}/g, (match, p1) => `)(...values)

})};

在vue中,每個元件都有乙個watch物件,它就是用來觀察屬性的變化,並將每個屬性的依賴關係

我總感覺我寫的東西總是沒有很好的設計感,總是沒有物件導向的感覺,功能能實現,未來擴充套件困難,不優雅

這就是我現在最大的問題,實際上,我也沒有遇到過將來要擴充套件的情況,寫的**都只是完成功能而已,太缺乏實踐。

最終我的實現:

firstname: 'lucy',

lastname: 'green',

age: 13

};// 替換字串為變數

const replacestr = (str, data) => \}/g, (match, p1) => `)(...values)

})};// 收集依賴

const collectdep = node => }'))

}} if (node.childnodes.length > 0)

};// 更新節點列表

const update = (nodelist, data) => )

}};const bindviewtodata = (el, data) => ,

set(newvalue)

})});

}};好多細節不確定,dom操作的某些屬性和方法也記不清了,估計手寫實現夠嗆,必須一遍除錯一遍寫

沒有很好的物件導向程式設計的思維,寫的**不優雅

多練多寫吧

前端框架系列之(mvvm)

前面我們介紹過了mvc 前端框架系列之 mvc mvp 前端框架系列之 mvp mvp中我們說過隨著業務邏輯的增加,ui的改變多的情況下,會有非常多的跟ui相關的case,這樣就會造成view的介面會很龐大。而mvvm就解決了這個問題,通過雙向繫結的機制,實現資料和ui內容,只要想改其中一方,另一方...

前端設計模式 MVP與MVVM

墨問蒼生 mvp設計模式 model 資料層 模組層 view 檢視層 以下是使用jquery實現的todolist 1 doctype html 23 html lang en 4 head 5 meta charset utf 8 6 title hello world title 7 scri...

2 11練習 練習5(1) p37

練習 5 1 修改前乙個練習,將dataonly中的資料在main 方法中賦值並列印出來。public class dataonlytest dataonly data new dataonly data.i 47 data.d 1.1 data.b false system.out.println...