如何獲取所有文字節點
defineproperty
和defineproperties
將字串替換為引數變數
如何標記依賴的元素
做乙個小型的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
就是我們存的表示式初始值
實現響應式,使用了defineproperty
將data
裡面每個屬性的setter
和getter
劫持
注意defineproperty
和``defineproperties的
setter`方法傳入的引數是不同的,實現的時候又搞混了
// 劫持data的setter,實現響應式更新
const keys = object.keys(data);
if (keys.length > 0) ,
set(newvalue)
})});
}
這個方法和之前練習過的《前端練習28 執行任意表示式》是一樣的,避免使用eval
和with
,使用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...