带你撸出一手好代码
第六节,JavaScript控件的实现

概述


先来看一段代码

 


var controlList = [];
controlList.add( new InputControl());
controlList.add( new SelectControl());
controlList.add( new DateTimeControl());
controlList.add( new CheckboxControl());
 
var html = "";
for(var i = 0; i < controlList.length; i++) {
html += controlList[i].renderHtml();
}
 
document.body.innerHTML = html;


这端代码其实就是fast dev控件机制的缩影, fast dev框架控件机制的核心思路便是如此。每个控件生成一部分HTML, 把所有控件的HTML组装在一起,就是整个页面的内容了。


1.png


如上图所示,表单页面的每一项都是一个控件, 这张页面由6个控件组成

 

<PageGroup id="bbq_deny" title="封号禁言">
    <Page mode="form" title="封号禁言">
        <Controls>
            <Control type="select" validation="required" name="type" title="类型">
                <ListItem title="封号" value="2"></ListItem>
                <ListItem title="禁言" value="1"></ListItem>
            </Control>
            <Control type="select" validation="required" name="op" title="操作">
                <ListItem title="添加" value="1"></ListItem>
                <ListItem title="解除" value="2"></ListItem>
            </Control>
            <Control type="input" validation="required|int" name="time" title="时长" placeholder="小时为单位"></Control>
            <Control type="input" validation="required" name="reason" title="原因"></Control>
            <Control type="select" validation="required" name="account_type" title="账号类型">
                <ListItem title="游戏内部GUID" value="1"></ListItem>
            </Control>
            <Control type="player_id_list" validation="required" name="user" title="玩家ID"></Control>
        </Controls>
        <listen></listen>
    </Page>
</PageGroup>

这是页面对应的配置文件,标红部分就是控件,框架程序会解析这个配置文件, 解析过程如下

  1.  控件的名称

  2. 通过名称定位到相应的控件文件

  3. 读书文件脚本

  4. 实例化对象

  5. 调用控件的renderHtml方法

  6. 组装html字符串

  7. 生成html页面

 

这张页面只使用了三种控件, 如下图所示


2.png


如果其他页面需要使用这些控件,直接在配置文件中指定控件名称就可以了,而不必重新实现代码, 因此控件机制可以最大限度的复用已有代码。

 

实现


Fast dev控件类有一系列继承结构

 

最顶层为 base_control 类

其次是  fbase 类,继承自 base_control

最终是我们实现的控件类, 换句话说,我们实现的控件类, 必须继承fbase类

 

Base_control类有一个抽象方法renderHtml

fbase类有两个抽象方法 getValue和setValue

因此,我们实现控件类必须实现这三个方法

 

以简单的input控件为例,代码如下

 

namespace gm2.control{
    export class input extends fbase{
        protected renderHtml():string {
            let placeholder = this.dataSource.get("placeholder") || "";
            let html = `<input type="text"  placeholder="${placeholder}" />`;
            return html;
        }
 
        public getValue(): any {
            let result = (this.getElement() as HTMLInputElement).value;
            return result;
        }
 
        public setValue( value: any ): void{
            let ele = this.getElement() as HTMLInputElement;
            ele.value = value;
        }
    }
}


为方便演示,这里使用的是 TypeScript代码,开发是换成JavaScript亦可行

 

renderHtml方法 


控件的renderHtml方法用来生成控件的html, 方法的返回值是字符串,因此此方法只需要返回控件的html字符串即可,html字符串的规格可以是任意的,可以尽情发挥创造力。

 

getValue方法 


getValue方法用于获得控件的值,上面的示例中的控件其实是一个html input表达项,因此它的值就是 input.value。 这个方法返回值可以是任意类型的值,在input控件类是字符串。 假如控件有多个输入, 如下图


3.png


显然, 用一个字符串是无法表示这么多项输入的。 对于这中类型的复杂控件,返回值可以使用JSON对象表示。 因此, 这个方法的返回值类型是不固定的。

 

这个方法的作用在于提交表单时,用于收集表单的数据,发送至服务器。

 

看下面的示例代码

 

var controlList = [];
controlList.add( new InputControl());
controlList.add( new SelectControl());
controlList.add( new DateTimeControl());
controlList.add( new CheckboxControl());
var data = [];
for(var i = 0; i < controlList.length; i++) {
    data.push(controlList[i].getValue());
}
ajaxSend( data );


当点击页面的提交按钮是,会调用如下代码,收集控件的值(表单的数据), 利用ajax发送至服务器。

 

setValue方法

 

 控件的 setValue方法,比较好理解, 它的作用就是填充表达的值。  想象一下有个编辑某条数据的页面,当我们打开页面是, 页面中的表单域的值默认是需要被填充, 如下图所示


4.png


setValue方法便是用来满足这个需求的

 

onRenderComplete事件 


当我们编写复杂的控件时, 可能会遇到需要为控件的HTML绑定事件的需求。 显然, 这在getValue方法里是无法完成的, 因为getValue方法运行是, 控件还只是字符串, 我们无法为字符串绑定事件。

 

我们需要在控件被转换成html元素的时候再为其绑定事件。

 

我们知道框架程序会调用控件的renderHTML, 将控件转换成html , 再将html 插入页面,这个时候控件也就被转换成了html元素。 与此同时,框架还会调用控件的renderComplete方法,通知控件, 已经把html 字符串转换成了html元素。 因此, 我们只要再问控件实现一个renderComplete方法即可,把操纵控件html的事件代码放在这个方法里即可。

 

        public onRenderComplete() {
            //dosomething
        }


以上便是fast dev的控件机制和实现方式, 虽然框架本身默认提供了不少控件,但是遇到特殊需求需要自定义开发控件是,可以参考此文档。


作者:陈大侠
日期:2017-10-10

留言(0条)

我要发表留言

您的大名 选填
电子邮箱 选填

欢迎关注微信公众号 「带你撸出一手好代码」

首页    GitHub 知乎 豆瓣 博客园