首頁  >  文章  >  web前端  >  JS控制項的生命週期介紹_javascript技巧

JS控制項的生命週期介紹_javascript技巧

WBOY
WBOY原創
2016-05-16 17:49:051089瀏覽

JS控件的生命周期跟其他平台UI的生命周期类似,但是又有自己的特点,我们只有将控件的生命周期划分清晰,所有的控件编写、mixins的编写和plugin的编写才能遵循控件的生命周期做统一的管理。在这里我把JS的生命周期定义为4部分:

1.initializer: 初始化,做一些不牵扯DOM操作的初始化操作
2.createDom: 创建 DOM,在这个过程中我们创建控件需要的DOM结构
3.renderUI: 生成控件的内部元素,在这里调用子控件的渲染方法,开启子控件的生命周期
4.bindUI: 绑定事件,可以绑定子控件事件也可以绑定内部DOM的事件
5.synUI: DOM结构以及子控件生成完毕后,我们在配置项中传入的值或者默认的配置项要应用到DOM上,例如 width,height,focusable之类的属性
6.destructor: 析构函数,移除控件,清理控件上的事件,清理子控件,清理控件自己的DOM以及控件的一些对其他控件的引用。


1

初始化:

控制初始化過程中做以下事情:
1.呼叫繼承的父類的初始化函數,包括原型鏈上的父類別和mixins
2.處理設定項,合併預設設定項和使用者傳入的設定項
3.處理綁定到改物件的事件
4.初始化外掛程式(plugin)
初始化完成後,是否建立DOM看具體的策略,類似ext的實現,可以延遲建立DOM

建立DOM

建立DOM的過程如下:
1.呼叫繼承的父類別的建立DOM的函數,包括原型鏈上的父類別和mixins
2.建立控制項的DOM
3.呼叫控制項插件的創建DOM的函數

渲染子控制與內部DOM操作

執行過程如下:
1.呼叫父類別的渲染函數,包含原型鏈上的父類別和mixins
2.呼叫插件的渲染函數
我們可以在頂層的父類別來初始化子控制項。好處是,子類別不需要做子控制項初始化的操作此時:
1.如果子控制項還未初始化則執行初始化
2.繼續執行子控制項的建立DOM、渲染子控制項、綁定事件、同步配置項目函數執行
綁定事件
由於此時控制項的DOM和內部的子控制項已經渲染完畢,則可以在子控制項或DOM上綁定事件。綁定事件的過程:
1.呼叫父類別的綁定事件方法,包括原型鏈上的父類別和mixins
2.呼叫父類別的綁定事件方式
注意:在子控制項或內部DOM上綁定事件時,使用委託,不要直接在子控制項或DOM上綁定事件,一旦子控制項新增或刪除,內部DOM變化都會造成事件失效。

同步配置項

首先說明一下什麼叫做同步配置項,前面我們在初始化控制項時,已經對配置項做過一定的處理(至於如何處理,後面講JS控制項屬性的時候會講到),但是配置項並未作用到DOM上或是內部子控制項上。
為什麼在這時候處理同步,而不是在創建DOM和渲染子控制項時,有2個原因:
1.在創建DOM和渲染子控制項時,所有的DOM和子控制項並未完整產生此時同步需要進行大量判斷
2.我們需要把同步配置項目的工作提取成方法,修改配置項時,內部DOM和子控件跟著變化。

例如:設定項裡有{ width : 100 }
1.如果我們在渲染DOM時同步,則可能把「width=100px;」直接設定到DOM上,而到我們需要修改這個width時,我們還需要寫一個函數來設定這個值。
2.反之,我們把同步配置項集中處理,將一個個的同步配置項的過程抽取成一個個函數,那麼我們初始化width的過程和修改width的過程完全一樣,這樣概念和邏輯就統一起來。
同步設定項的過程仍如其他步驟一樣:
1.呼叫父類別的同步方法,包括原型鏈上的父類別和mixins
2.呼叫外掛程式(plugin)的同步方法
注意:我們應該可以配置一個配置項是否在此時同步,原因有很多,例如多個配置項會產生相同操作,如果多個配置項同時同步,那麼一個過程會重複執行多次。
移除控制
任何物件都有建構函數,必定也有析構函數,但是這個函數往往是大家最容易忽略的地方,但是也是非常重要的地方,暫且不說記憶體外洩之類的問題,就是如果一個控制項的移除工作做得不夠好,會對正常的使用帶來很大的麻煩。
這個函數又是最不好寫的一個函數,因為它需要處理以下工作:
1.清理使用的其他控件,是否也移除看具體情形。區分關聯和聚合
2.清理子控制
3.清理綁定到控制項和DOM上的事件
4.移除DOM
5.清理變數的引用,這個比較麻煩和繁瑣,所以我們需要對控制項的參考做統一的管理
同樣此函數也要執行:
1.呼叫父類的析構函數,包括原型鏈上的父類和mixins
2.調用插件的析構函數

問題

上面講的全部是具體的步驟,但是在實現的時候遇到了一系列的問題:
1.呼叫父類別的方法有問題
1)呼叫原型鏈上的父類別方法,只能使用className.superclass.method.call(this)這類的方法,this.constructor.superclass.method.call(this )不能使用,原因在js 控制項繼承的extend一章中有講到,這種呼叫方式繁瑣而且維護不方便。
2)呼叫mixins上的方法,在JS 繼承mixins一章中我講到過mixins的實作原理,覆寫同名方法,mixins的方法其實已經作為控制項的prototype上的方法,所以最好不要使用同名方法,如果多個mixins都是用renderUI,synUI之類的方法,而繼承這些mixins的控制項並沒有實作renderUI這類方法,那麼就會被覆寫。
2.呼叫外掛程式的方法也存在問題
1)我們需要取得目前控制項的參考

解決方式:

1.針對父呼叫類別的方法我們可以在控制項渲染時,按照原型鏈的順序,先呼叫父類別的方法再呼叫子類別的方法直到目前控制項:


如上面的繼承關係,我們執行C.renderUI()時,依照繼承原型鏈的頂層向下執行。
2. 執行minxins的方法,我們執行renderUI時,去依序執行 mixin 的__renderUI方法。
3. 執行父類別的renderUI 時,如果也存在mixins那麼執行mixin的 __renderUI方法。



圖3

如上圖: inherits表示原型鏈繼承,extends表示mixin擴充
那麼c.renderUI的執行過程如下:

A.renderUI ->D.__renderUI->B.renderUI- >E.__renderUI->C.renderUI
3. 呼叫插件方法時需要傳遞控製本身的引用即可,如:
plugin1.render(this)
4. 析構函數destructor比較特使,執行的順序跟上面2講的順序有所不同:
子類destructor -> 子類擴展destructor -> 父類destructor -> 父類擴展destructor
按照圖3的繼承結構其析構函數執行的順序是:
C. destructor ->E.__destructor->B.destructor->E.__destructor->a.destructor
原因是,子類的一些引用依賴於父類或擴展類,如果父類別和擴充類別先執行析構函數,那麼子類別在使用某些變數/屬性時會報錯。

這一節我把控制項的生命週期講了一遍,所有的著一些都是來自於KISSY框架的UIBase,感興趣的可以去看一下,非常精彩的實現 http://docs.kissyui.com/kissy/docs/#!/api/KISSY.Component.UIBase

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn