摘要:在等庫(kù)中,開(kāi)頭的屬性方法都是框架自用的。使用或者更新的,就能得到所有訪問(wèn)器屬性的定義對(duì)象,然后合成。至此,內(nèi)部各種概念的關(guān)系圖如下框架設(shè)計(jì)第三版,敬請(qǐng)期待
不是有了Object.defineProperty, Proxy或Reflect,放進(jìn)一個(gè)對(duì)象就new出一個(gè)ViewModel出來(lái)。只能說(shuō),它們是必要條件。我們需要將要監(jiān)聽(tīng)的屬性變成訪問(wèn)器屬性,所有訪問(wèn)器屬性都是共用同一套setter, getter方法。getter里面做依賴收集(不是必須的),setter里做視圖刷新或觸發(fā)該屬性的$watch回調(diào)。在此之前,我們需要完成一套觀察者模式,就是github中常見(jiàn)的EventEmitter庫(kù):
https://github.com/Olical/Eve...
https://github.com/asyncly/Ev...
https://github.com/primus/eve...
但這些庫(kù)的訂閱數(shù)組都是放函數(shù)。我們需要放綁定對(duì)象,需要改造一下,并且改成$watch, $fire接口。
var EventBus = { $watch: function (type, callback) { var binding = callback if (typeof callback === "function") { binding = { expr: type, update: callback } } var bus = this.$events var list = bus[type] if (!list) { list = bus[type] = [] } function unwatch() { avalon.Array.remove(list, binding) if(!list.length){ delete bus[type] } } list.push(binding) return unwatch }, $fire: function (type, value) { var list = this.$events[type] if (list && lsit.length) { for (var i = 0, obj; obj = list[i++];) { obj.update() } } } }
然后我們?cè)贋樗砑右粋€(gè)$id,用于標(biāo)記這個(gè)VM是作用于頁(yè)面某個(gè)元素上的。
var vm = avalon.define({ $id: "test", aaa: 1, bbb: 2 }){{@aaa}}
我們看avalon.define的一個(gè)簡(jiǎn)單實(shí)現(xiàn):
avalon.define = function(obj) { var vm = {} var other = {} for (var name in obj) { if (typeof obj[name] !== "function" && name.charAt(0) !== "$") { (function (key, value) { function get(){ //在avalon1.4,1.5中這里會(huì)進(jìn)行動(dòng)態(tài)依賴收集,詳見(jiàn)這里 //https://github.com/RubyLouvre/avalon/blob/1.5/src/10%20dependency.js return get._value } get._value = value Object.defineProperty(obj, key, { set: function (newValue) { if(newValue !== get._value){ get._value = newValue if(vm.$hashcode) vm.$fire(key, newValue) } return newValue }, get: get }) })(name, obj[name]) }else{ other[name] = obj[name] } } for(var name in other){ vm[name] = other } vm.$events = {} vm.$hashcode = new Date - Math.random() vm.$fire = EventBus.$fire vm.$watch = EventBus.$watch return avalon.vmodels[vm.$id] = vm }
此外,你可以添加更多以$開(kāi)頭的屬性方法,來(lái)增強(qiáng)它的功能。在avalon, angular等庫(kù)中,$開(kāi)頭的屬性方法都是框架自用的。avalon2的一個(gè)簡(jiǎn)單的vm是藏了許多不可遍歷的$xxx屬性方法:
那么如何將綁定屬性放進(jìn)vm.$events.aaa數(shù)組中呢。這就要靠掃描機(jī)制。從上到下掃描。
avalon.scan = function (el, vm) { scanNodes([el], vm) } function scanNodes(array, vm) { for (var i = 0, el; el = array[i++]; ) { switch (el.nodeType) { case 1: scanTag(el, vm) break case 3: scanText(el, vm) break } } } function scanTag(el, vm){ var id = el.getAttribute("ms-controller") if(id && avalon.vmodels[id]){ var vm2 = avalon.vmodels[id] if(vm && vm2 && vm == vm2){ vm = mergeVM(vm,vm2) }else{ vm = vm2 } el.removeAttribute("ms-controller") } var bindings = scanAttrs(el,vm) for(var i = 0, b; b = bindings[i++];){ vm.$watch(b.expr, b) //重點(diǎn) } if(el.children && el.children.length){ scanNodes(el.children, vm) } } function scanText(){ // 用正則檢測(cè)是否有花括號(hào) // 有則轉(zhuǎn)換為綁定對(duì)象 // 并進(jìn)行vm.$watch } function scanAttrs(){ //遍歷el.attributes中所有對(duì)象,看name是否以ms-開(kāi)頭 }
那么如何將綁定屬性放進(jìn)vm.$events.aaa數(shù)組中呢。這就要靠掃描機(jī)制。從上到下掃描。
avalon.scan = function (el, vm) { scanNodes([el], vm) } function scanNodes(array, vm) { for (var i = 0, el; el = array[i++]; ) { switch (el.nodeType) { case 1: scanTag(el, vm) break case 3: scanText(el, vm) break } } } function scanTag(el, vm){ var id = el.getAttribute("ms-controller") if(id && avalon.vmodels[id]){ var vm2 = avalon.vmodels[id] if(vm && vm2 && vm == vm2){ vm = mergeVM(vm,vm2) }else{ vm = vm2 } el.removeAttribute("ms-controller") } var bindings = scanAttrs(el,vm) for(var i = 0, b; b = bindings[i++];){ vm.$watch(b.expr, b) //重點(diǎn) } if(el.children && el.children.length){ scanNodes(el.children, vm) } } function scanText(){ // 用正則檢測(cè)是否有花括號(hào) // 有則轉(zhuǎn)換為綁定對(duì)象 // 并進(jìn)行vm.$watch } function scanAttrs(){ //遍歷el.attributes中所有對(duì)象,看name是否以ms-開(kāi)頭 }
里面用到一個(gè)mergeVM方法,其實(shí)也簡(jiǎn)單,就是將兩個(gè)VM合并成一個(gè)新的VM。使用Object.getOwnPropertyDescriptor或者更新的Object.getOwnPropertyDescriptors,就能得到所有訪問(wèn)器屬性的定義對(duì)象,然后合成。如果是古老瀏覽器,我們可以將訪問(wèn)器屬性放到一個(gè)叫$accessors對(duì)象上。
現(xiàn)在我們這個(gè)VM是很簡(jiǎn)單的,它只支持一重屬性,如果屬性的屬性也是對(duì)象呢。這個(gè)我們需要將這define方法遞 歸一下不就行了嗎?!對(duì)于數(shù)組的監(jiān)控,業(yè)界流行的方法是重寫(xiě)數(shù)組的大部分方法,然后再加上一些移除數(shù)組的方法。
至此,avalon內(nèi)部各種概念的關(guān)系圖如下:
from 《javascript框架設(shè)計(jì)》第三版,敬請(qǐng)期待
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/87935.html
摘要:換言之,的對(duì)應(yīng)的,此外它還有。它們共同構(gòu)成的監(jiān)控系統(tǒng)。和是相輔相成的。兩者一起,構(gòu)成了作用域的核心功能數(shù)據(jù)變化的響應(yīng)。迭代的最大值稱為。框架設(shè)計(jì)第三版,敬請(qǐng)期待 angular的ViewModel有一個(gè)專門的官方術(shù)語(yǔ)叫$scope, 它只是一個(gè)普通構(gòu)造器(Scope)的實(shí)例。換言之,它是一個(gè)普通的JS對(duì)象。為了實(shí)現(xiàn)MVVM框架通常宣傳的那種改變數(shù)據(jù)即改變視圖的魔幻效果,它得裝備上更多更...
摘要:棧是操作系統(tǒng)在建立某個(gè)進(jìn)程時(shí)或者線程為這個(gè)線程建立的存儲(chǔ)區(qū)域。在具有多線程機(jī)制的操作系統(tǒng)中,處理機(jī)調(diào)度的基本單位不是進(jìn)程而是線程。一個(gè)進(jìn)程可以有多個(gè)線程,而且至少有一個(gè)可執(zhí)行線程。 WEB前端面試題的記錄(二) 1、一次完整的HTTP事務(wù)是怎樣的一個(gè)過(guò)程:基本流程: 域名解析 發(fā)起TCP的3次握手 建立TCP連接后發(fā)起http請(qǐng)求 服務(wù)器端響應(yīng)http請(qǐng)求,瀏覽器得到html代碼 瀏...
摘要:最終選擇了兼容到的,終于使用上框架,雖然它只是個(gè)。沒(méi)有對(duì)比就沒(méi)有傷害本來(lái)想著技術(shù)棧統(tǒng)一,移動(dòng)端也準(zhǔn)備使用。于是,之后對(duì)移動(dòng)端的技術(shù)選型上更加慎重了,最終采用了文檔更漂亮的。易用還真不易用,坑還真多。 吐槽 avalon.js 歷史背景 需求重大調(diào)整,所有業(yè)務(wù)推倒重來(lái)(pc端主要任務(wù)涉及管理后臺(tái)類型的網(wǎng)站); 開(kāi)發(fā)周期很緊,過(guò)年前要上線; 公司pc端業(yè)務(wù)要求兼容到ie8; 2015年前...
摘要:相關(guān)組件版本最近,在公司的項(xiàng)目中,要開(kāi)發(fā)一個(gè)使用瀑布流的前臺(tái),衡量了各種解決方案后,還是覺(jué)得最成熟,所以就選用了它。測(cè)試的結(jié)果很令人沮喪,依然沒(méi)有控制節(jié)點(diǎn)的位置,所以應(yīng)該不是這個(gè)問(wèn)題。 相關(guān)組件版本:avalon 1.3.6、masonry 3.1.5 最近,在公司的項(xiàng)目中,要開(kāi)發(fā)一個(gè)使用瀑布流的前臺(tái),衡量了各種解決方案后,還是覺(jué)得masonry最成熟,所以就選用了它。而在之前開(kāi)發(fā)后臺(tái)...
摘要:給人印象中,樹(shù)組件是非常令人畏懼的一個(gè)組件,超級(jí)復(fù)雜,超級(jí)難寫(xiě)。但使用來(lái)做,這卻是級(jí)其簡(jiǎn)單的一件事。換言之,我們用元素作為樹(shù)的節(jié)點(diǎn),那么樹(shù)組件內(nèi)部也需要存在樹(shù)組件,需要形成遞歸結(jié)構(gòu)。的機(jī)制又是出場(chǎng)的時(shí)候了。 給人印象中,樹(shù)組件是非常令人畏懼的一個(gè)組件,超級(jí)復(fù)雜,超級(jí)難寫(xiě)。但使用avalon2來(lái)做,這卻是級(jí)其簡(jiǎn)單的一件事。首先從樣式入做,無(wú)序列表是天然可用的樹(shù)結(jié)構(gòu),幾個(gè)UL元素套在一起,...
閱讀 3527·2023-04-25 14:57
閱讀 2574·2021-11-22 14:56
閱讀 2098·2021-09-29 09:45
閱讀 1779·2021-09-22 15:53
閱讀 3327·2021-08-25 09:41
閱讀 908·2019-08-29 15:22
閱讀 3307·2019-08-29 13:22
閱讀 3132·2019-08-29 13:08