Fork me on GitHub
构建一个前端库-做一个富客户端的基类

基类,我们需要一个基类。

数据库访问我们通常有一个基类,用于操作的统一性。

那么,我们现在需要一个富客户端的前端基类。

为什么我们需要它。

 

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它。

 
 
posted on 2013-01-15 22:13  HackerVirus  阅读(175)  评论(0编辑  收藏  举报