概述

Ext.Component是所有Ext元件的基類,這在Ext.Component的API中第一句話就提到了。然後第二段說明了它包含的基本功
能:隱藏/顯示、啟用/禁用以及尺寸控制等。除了以上這些基本功能,其實還包含了很多東西。當然,在API中不可能面面俱到,那麼,我們應當如何去理解這
個元件基類呢?

Ext.Component===DIV

如果將一個Ext.Component渲染到頁面,會看到該元件會簡單的在頁面中新增一個DIV標記,就是這麼簡單。也就是
說,Ext.Component就相當於一個DIV標記。那麼接下來的問題,我可以用這個做些什麼?如果是單純的在頁面中使用一個DIV標記,我們可以讓
它來顯示內容,也可以用它來與其他DIV標記構建頁面佈局,總的來說,就是讓它做你想做的事情。

既然一個DIV標記可以做那麼多事情,那麼如何在Ext.Component實現你所想做的呢?

顯示內容

要在DIV內顯示內容,有兩種方式,一是直接把內容新增在DIV內進行顯示,一是找到DIV標記,再將內容新增到DIV標記內。如果你是
Ext.Component的設計者,你將如何實現這兩種方式呢?一般情況下,第一種方式,都會將內容寫到一個變數裡,然後用字串組合的方式將DIV標
記與內容結合成一個字串再輸出, 而第二種方式基本都是使用DOM操作先獲取元素,再使用元素的innerHTML屬性將內容寫到DIV標記內。

以上是在不使用任何javascript框架時的實現的方式,而對於Ext.Component這樣需要例項化後才能使用的類,如何來實現呢?如果
對類設計比較熟悉的話,第一種方式的實現肯定是在類例項化時,將內容繫結到屬性上,然後在類內組合字串進行輸出,第二種方式的實現基本就是提供一個方法
進行操作了。因而,為了能處理這兩種方式,Ext.Component就必須提供一個屬性來存放初始化時的內容,還要提供一個方法來來處理內容的更新。在
Ext.Component內實現這兩個功能的就是HTML配置項和update方法。


注意:配置項(Config
options)嚴格意義上來說就是屬性,但是在Javascript中,要區分哪些屬性是允許初始化的,哪些屬性是不允許初始化的,尤其是對於只讀屬性
這樣的屬性,要區分實在不容易,如果在API中不加區分,就會增加出錯的機率,因而在API中特意新增了配置項這一專屬名稱以示區別。


當然,對於封裝了底層DOM操作和提供了模板的框架了來說,不會真的使用那麼簡單的實現方法來實現這兩種操作。因而,不要把我說的就認為是
Ext.Component的實現方式。在這裡,只要瞭解它的基本實現思路就行了。探究起來,Ext.Component實現這兩種方式是相當複雜的,復
雜的地方主要在渲染流程。這個渲染流程是通過Ext.util.Renderable類實現的,它通過混入(mixins)的方式混入到了
Ext.Component中。在這個Ext.util.Renderable類中,渲染HTML程式碼主要是靠模板與Ext.DomHelper來實現
的,有興趣的可自行研究一下,在這裡就不深入了。

樣式

對於DIV標記來說,不可缺少的一環當然是為它定義樣式或樣式類,而這個,與內容的思路是一樣的,因而也必須提供相應的配置項與方法,於是就有
style和cls配置項以及addCls、removeCls和setStyle方法。至於為什麼樣式類拆分成了兩個方法,而樣式只有一個方法,具體原
因我只知道樣式類在Ext
JS的元件中經常需要新增或減少,使用兩個方法會更方便,其實還有第三個方法replaceCls,但至於樣式為什麼只有setStyle方法,具體原因
暫時沒想到。

尺寸

控制DIV標記的尺寸,以控制DIV標記的可視範圍也是經常會使用到的,因而,這個功能是必須有的。

滾動條

當DIV標記固定了尺寸後,內容有可能會超出可視區域,這時候,你是希望顯示滾動條,讓使用者滾動檢視內容,還是不顯示滾動條,直接忽略多餘的內容呢?這也是要考慮的。

隱藏/顯示

DIV的顯示和隱藏,這個也是會經常使用到的,因而也需要實現。

啟用/禁用

當使用DIV標記來實現按鈕功能的時候,這個就很有用了。

簡化樣式設定

一個DIV標記可設定的屬性很多,如果某些屬性需要經常使用到,如何簡化這些屬性的輸入呢?不可能總是使用style配置項吧?解決辦法就是直接通過配置項的方式來直接輸入,如padding、margin、border與tabIndex等。

id

說到簡化樣式設定,不得不說一下id。為DIV標記設定一個id,可以便於快速獲取DIV元素,以便進行操作。而對於元件來說了,id配置項設定的
值除了昨晚元素的id外,還可以作為元件的id使用,因而具有雙重作用。但設定太多id,並不是好事,因為這很容易造成id衝突,因而要慎用。另一直可替
代的方法是itemId,不過在Ext JS 5和6,有更好的reference可以使用。助於id所涉及的相關元件查詢知識,可以另開一篇文章講述。

浮動的DIV

不少網站都可以看到一些浮動的元素,如浮動的邊欄,彈窗視窗等等,對於一個框架來說,這當然不能少,畢竟視窗、框架的資訊視窗都需要使用該功能。為
了將浮動功能與基本功能區分開來,便於維護,框架將浮動功能都集中到了Ext.util.Floating類,然後通過混入功能將浮動功能混入
Ext.Component類。

動畫

有動畫功能的框架才夠炫,必不可少。在Ext.Component是通過混入Ext.util.Animate實現。

事件

對於事件,這個不用多說,怎麼可能缺少呢。要注意的是,在框架中,包含了兩種事件,一種是瀏覽器事件,一種是內部事件。

瀏覽器事件指的是使用者與頁面交換所產生的事件,這個是通過Ext.dom.ElementEvent實現的,在使用Ext.dom.Element
進行DOM操作時候,就可以為元素繫結或解除事件。Ext.Component元件必不可少的功能就是DOM操作,因而可通過
Ext.dom.Element來處理瀏覽器事件。

內部事件是指Ext
JS框架內部的產生事件,如儲存(Store)載入了資料,它要通知元件去更新顯示,而這就需要通過內部事件進行處理。瞭解清楚這個非常重要,例如,儲存
已經載入資料了,但是元件並沒有更新顯示,到底哪裡出錯了呢?如果瞭解了內部事件處理流程,這個就很容易跟蹤了,例子中的處理流程就是,儲存通過讀取器
(Reader)呼叫Ajax去伺服器載入資料,資料讀取後,代理(Proxy)會再將資料轉換為符合儲存定義格式的資料,當處理完成後,儲存發現有新的
資料,就會觸發儲存的Refresh事件,在元件中,當監聽到Refresh事件的時候,說明儲存已經讀取了資料,可以更新顯示了。根據這個流程,如果數
據已讀取,而沒有顯示,那說明存在的問題包括:資料讀取錯誤、資料轉換錯誤、儲存沒有觸發Refresh事件,元件沒有執行更新顯示的程式碼或更新的時候出
現錯誤。通過逐一排查和跟蹤分析這幾個流程就很容易找到問題所在了。

在Ext.Component中,內部事件是通過混入Ext.util.Observable類實現的。

Ext.Component與模板

在上面提及過,Ext.Component是使用模板與Ext.DomHelper來渲染元素的,也就是說,我不一定要把
Ext.Component渲染為預設的DIV標記,那麼該如何來實現呢?根據上面的思路,提供一個配置項就行了,如果是使用模板,可以使用tpl配置
項,如果使用Ext.DomHelper,則可繼續使用html配置項。

既然可以使用模板,那意味著可以渲染資料,那就必須預留資料介面,因而有了配置項data和setData方法。

遠端載入

如果內容是需要遠端載入後渲染的,哪怎麼辦?簡單,預留介面就行了,這就是loader配置項,它是通過Ext.ComponentLoader物件來實現遠端載入的。

我要直接操控元件生成的元素

雖然使用Ext
JS,一般不需要直接操控元件生成的元素,但是確實會存在這方面的需求,因為,必須預留這方面的介面。因而,在元件中提供了getEl方法,用來返回元件
所生成的元素中的最頂層的元素,有了這個元素,就可以操控元素及其子元素了,不過,要注意的是,getEl方法返回的是Ext.dom.Element對
象的例項,而不是HTMLElement物件。

新增其他功能

經過以上一些處理,Ext.Component的功能就已經相當強大了,但可能還有有一些可能沒有考慮到的功能,而這就可以通過混入這樣的方式將新功能混入到元件中。在Ext.Component中還混入了以下功能:

  • Ext.mixin.Inheritable:為元件提供可繼承的配置屬性和配置方法。

  • Ext.util.Positionable:為元件物件提供定位介面。

  • Ext.mixin.ComponentDelegation:為元件提供委託事件。

  • Ext.mixin.Bindable:為元件提供bind配置項來連線檢視模型。

  • Ext.util.ElementContainer:為元件提供操控子元素(元件)的功能。

  • Ext.state.Stateful:為元件提供狀態功能。

  • Ext.util.Focusable:為元件提供獲取焦點的功能。

  • Ext.mixin.Accessible:為元件提供可訪問性方面的功能。

  • Ext.util.KeyboardInteractive: 為元件提供鍵盤互動功能。

小結

通過以上的分析,不知道你是否對元件有了更多的瞭解?總的來說,我就是基於這樣一種思路去了解和認識元件的,這種方式的主要好處就是便於記憶元件的
常用配置項和方法。尤其是在需要解決一些問題或實現一些沒有提供的功能時候,可以大致知道是否能實現,如何去實現。如果大家在這方面有什麼看法或意見,請
留言給我,多交流是非常有益的。

在實現了元件基類後,元件就劃分為容器類元件與非容器類元件兩條主線不斷派生出不同的元件,在下一文,將講述容器類元件。


請大家尊重作者的辛勤勞動,未經允許,請不要轉載本文,畢竟讀者的支援是作者撰寫文章的動力。