JS控制項 生命週期

2022-03-08 18:38:08 字數 3651 閱讀 2562

js控制項的生命週期跟其他平台ui的生命週期類似,但是又有自己的特點,我們只有將控制項的生命週期劃分清晰,所有的控制項編寫、mixins的編寫和plugin的編寫才能遵循控制項的生命週期做統一的管理。在這裡我把js的生命週期定義為6部分:

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的過程如下:

1.呼叫繼承的父類的建立dom的函式,包括原型鏈上的父類和mixins

2.建立控制項的dom

3.呼叫控制項外掛程式的建立dom的函式

執行過程如下:

1.呼叫父類的渲染函式,包括原型鏈上的父類和mixins

2.呼叫外掛程式的渲染函式

我們可以在頂級的父類來初始化子控制項。好處是,子類不需要做子控制項初始化的操作此時:

1.如果子控制項還未初始化則執行初始化

2.繼續執行子控制項的建立dom、渲染子控制項、繫結事件、同步配置項函式執行

由於此時控制項的dom和內部的子控制項已經渲染完畢,則可以在子控制項或者dom上繫結事件。繫結事件的過程:

1.呼叫父類的繫結事件方法,包括原型鏈上的父類和mixins

2.呼叫外掛程式(plugin)的繫結事件方式

注意:在子控制項或者內部dom上繫結事件時,使用委託,不要直接在子控制項或者dom上繫結事件,一旦子控制項新增或者刪除,內部dom變化都會引起事件失效。

首先說明一下什麼叫做同步配置項,前面我們在初始化控制項時,已經對配置項做過一定的處理(至於如何處理,後面講 js控制項屬性

的時候會講到),但是配置項並未作用到dom上或者內部子控制項上。

為什麼在這時候處理同步,而不是在建立dom和渲染子控制項時,有2個原因:

1.在建立dom和渲染子控制項時,所有的dom和子控制項並未完整生成此時同步需要進行大量判斷

2.我們需要把同步配置項的工作提取成方法,修改配置項時,內部dom和子控制項跟著變化。

例如:配置項裡有

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,感興趣的可以去看一下,非常精彩的實現

React 生命週期 生命週期方法

生命週期 掛載 更新 解除安裝 元件被建立 執行初始化 並被掛載到dom中,完成元件的第一次渲染 constructor props getderivedstatefromprops props,state render componentdidmount 元件被建立時會首先呼叫元件的構造方法,接受...

actived生命週期 Vuejs 生命週期

每個 vue 例項在被建立時都要經過一系列的初始化過程。如需要設定資料監聽 編譯模板 將例項掛載到 dom 並在資料變化時更新 dom 等。同時在這個過程中也會執行一些叫做生命週期鉤子的函式,這給了使用者在不同階段新增自己的 的機會。乙個 vue 例項 我們建立乙個 vue 例項,並在每個階段驗證 ...

網頁生命週期 動態新增控制項

有程式動態建立控制項 1,獲取文字框內容 規避輸入問題try catch 2,在panel中按數量新增文字框pnl.controls.add ctl 3,新增時同時在文字框中設定值 4,測算總共控制項數量 controls.count 5,判斷某控制項是不是文字框 control is textbo...