基類,我們需要一個基類。
數據庫訪問我們通常有一個基類,用於操作的統一性。
那么,我們現在需要一個富客戶端的前端基類。
為什么我們需要它。
1.我們需要一個dom元素與javascript之間的橋梁。
2.我們需要一個可伸縮布局的方案。
3.它是可拖動的。
4.它是可改變大小的。
5.它是可參數化配置的。
6.它是可綁定數據源的。
7.它是可隱藏也可延遲加載的。
我們需要這么一個基類,避免我們重復寫很多相似的代碼、
我們一個一個來說它們的實現。
1.構建橋梁
通常我們都用document.getElementById來用javascript獲取一個dom元素。
但這里,我們富客戶端的方案是用javascript生成dom對象,並且用jQuery輔助我們的元素獲取。
所以首先我們來動態構建html
if (v.modal == 1) { //允許多個模態對象並存 if (_modal_layer) _modal_layer += 5; else _modal_layer = radf.MODAL_LAYER; v.parent = _root; v.zIndex = _modal_layer + 1; } else if (v.modal == 2) { //只允許同時存在一個非模態對象,后面的非模態對象會替代前面的非模態對象 if (_modeless) { _modeless._param.modal = 0; if (_modeless._loaded) _modeless.sendToTop(); else _modeless._param.zIndex = 1; } v.parent = _root; v.zIndex = radf.MODELESS_LAYER; _modeless = this; } //html定義 if (v.id) this._html= v.tagName + " id=" + v.id + " class='" + v.className + "' _objIndex=" + this._objIndex + " _loadMode=" + v.loadMode; else this._html= v.tagName + " class=" + v.className + " _objIndex=" + this._objIndex + " _loadMode=" + v.loadMode; if (v.tip) this._html += " title='" + v.tip + "' "; //樣式屬性 this._style = " style='position:absolute;overflow:" + v.scrollBar; if (this._padding.text) this._style+= ";padding:" + this._padding.text; //留白 if (this._borderWidth.text) this._style+= ";border-width:" + this._borderWidth.text;//邊框寬度 if (v.borderStyle) this._style+= ";border-style:" + v.borderStyle; //邊框樣式 if (v.borderColor) this._style+= ";border-color:" + v.borderColor; //邊框顏色 if (v.background) this._style+= ";background:" + v.background; //背景 if (v.style) this._style += ";" + v.style; //樣式 if (v.minWidth == 0 ) v.minWidth = this._borderWidth.left + this._borderWidth.right + this._padding.left + this._padding.right; if (v.minHeight == 0 ) v.minHeight = this._borderWidth.top + this._borderWidth.bottom + this._padding.top + this._padding.bottom; //位置屬性 this._top = v.top; this._left = v.left; this._y0 = this._padding.top + this._borderWidth.top; this._x0 = this._padding.left + this._borderWidth.left; this._oldY0 = this._y0 this._oldX0 = this._x0;
然后,我們把這個html用jQuery包裝起來。
Control.prototype.$ = $(this._html);
最后,我們用一個全局的數組來保存所有產生的javascript對象。
var radf._objIndex = []; this._objIndex = radf._obj.length; radf._obj[this._objIndex] = this;
這樣,我們在這個對象內部就擁有了它自己的jQuery對象,在全局上也擁有了一個可控的Javascript對象。
我們可以輕易的在全局使用這個javascript也可以方便的在原型中使用jQuery對象。
2.可伸縮布局的方案
浮動和清除浮動是前端永恆的話題。但是我們的方案中,用了一個神奇的東西。
position:absolute
好吧,我們都知道它是一個禁果。
它非常輕易的可以實現元素的隨意擺放,但也非常損耗性能。
使用它,我們要注意幾件事
1.margin,padding不再可使用。
2.需要一個可承受的性能損耗。
3.z-index變得十分重要。
4.可控的元素嵌套。
5.可實現的算法。
所以我們寫了三種情況下的算法。
//1. 重畫大小不依賴於父組件的子組件 this._redrawFirst(); //2. 確定自適應方式下的組件大小 this._redrawSecond(); //3. 重畫大小依賴於父組件的子組件 this._redrawThird(); //4. 布局子組件 if (this._layout) this._layout();
由於我們在布局的時候,ajax操作會異步執行,
所以經過測試,在數據到來的零點幾秒之內,
dom元素的布局是完成了,所以算法的時間消耗是可以接受的。
3.可拖動及可以改變大小
絕對定位的原因,可拖動變得十分簡單。
改變大小的問題,在於改變大小后,調用上面的方法,重算父窗口就ok了。
4.可配置的參數
Control.prototype.create = function(v) { //設置缺省參數 //for (var i in this._defaultParam) if (v[i]==null) v[i] = this._defaultParam[i]; radf.Utility.copy(this._defaultParam,v); //保存初始化參數 this._param = v; //設置父對象 if (v.parent == null || v.modal > 0 ) { if (_root) v.parent = _root; else v.parent = root(); } v.parent._addChild(this); //建立對象索引 this._objIndex = radf._obj.length; radf._obj[this._objIndex] = this; //初始化參數 this._iniParam(v); }
我們看一下一個類實例化的時候會做些什么, 將默認參數存起來,將填寫的參數加入到實例中,
將父對象保存起來,建立對象的索引號。
5.可綁定數據
我之前提到的MVVM模式的優勢在於,數據先到的話,就會將數據存起來,
dom先加載了,就會將外框的div先加載,而里面的數據,例如table中的td,在數據到來的時候再加載。
並且,在dom元素操作的時候,也會通過基類寫好的方法,將數據重新綁到數據對象。
或者在操作數據對象,例如重新從數據庫取出數據后,就會重新生成dom元素。
這樣,一個可綁定的組件基類就ok了。
7.它是可隱藏並且可以延遲加載
我們知道,當一個dom對象需要隱藏,將它的display設成none,就會讓這個元素不占位的隱藏。
如果用visible的話,就會占位隱藏。由於富客戶端的作法,我們基本上沒有外鏈,所有操作都在一個頁面上,
空間非常的局限。所以一個可以伸縮的頁面是非常必要的。
那么我們使用display將單個組件變得可以隱藏起來,以用來顯示全全部內容。
那么延遲加載就很好理解了,如果元素被設為visible:false,那我們就不做這個元素的數據綁定,也不會這個對象的寬高,
只有一個空的div在那里。當這個元素被要求顯示,例如一個折疊框打開時候,我們再去load它。