众联BreezeCMS设计思路已经描述过,下面要简要说明一下其对应的定制方法,从其定制方法中,亦可以看到对应的设计原理:
定制概述
CMSMgr的定制关键是Controler。参见设计思路,Controler是管理和控制一个独立的管理页面。而所有的decorate是被Controler使用的组件。
因此定制关键不是decorate,decorate一般不做定制,只被使用。
定制的关键是Controler,decorate中的操作和按钮,这些操作反向调用Controler的方法。
Controler有两类方法,第一类方法是显示类型方法,这类方法是基础方法,遵循着数据查询到页面显示的顺序。第二类方法,是给显示页面后的第二次操作API显示。
Control的入口函数是showContent。如下是showControl的函数内容:
//获取decorate
var decorates = this.API.private("getDecorates");
//整理显示数据
var allData = this.API.private('processorShowData');
//if (allData为空){直接退出,不处理
//--这种情况就是超时或者查询数据失败
if(!allData){
return;
}
//}
//创建所有decorate
this.createDecorateApps(decorates, allData);
//显示前调整数据
this.API.private('beforeShow', allData);
//显示内容
this.API.show(viewid, allData);
//显示后调整
this.API.private('afterShow', allData);
//权限校验
this.checkAuth($("#CMSMgrControl"));
可见使用的showContent方法仅仅入口方法,而它将整个显示方法拆分成多个小步骤,每个步骤都封装成完整的方法,showContent是将这些函数拼装起来。
Controler的默认方法
在gadget/CMSMgrControl目录下的CMSMgrControl是一个controler的基类。如下是这个基类的默认方法:
handleMetaDataBefore 处理和转换查询出来的元数据格式
handleDataBefore 处理查询出来的数据
deleteContent 删除选中数据
update 更新数据
addNew 添加数据
queryDataCount 根据参数查询数据总数
handleDataAfter 数据后处理函数
checkAuth 校验函数
createDecorateApps 创建所有app
openMask 打开蒙板层
showContent 最基本的显示基类,显示整个页面
queryData 请求数据方法,注意,部分查询条件是被长期保存的,这些条件会对后面的查询产生影响。
这个时候,就要使用'-'标识强制忽略之前的某些记录的查询条件
私有方法如下:
getDecorates 获取所有decorates的信息
components 组件的字符串
processorShowData 处理所有显示数据
beforeShow 给在显示前的一个调整,这个时候,所有的decorate已经创建,可以独立设置某个decorate的信息
afterShow 显示结束后的数据处理,也是个空方法,接受处理中。
显示原理
showContent函数里面,显示函数就是,this.API.show(viewid, allData);
视图id可以在onCreate函数调用中传入。
由此可见,最简单的情况下,实际定制Control时,只要继承这个control后,传入一个我们自定义的一个视图id,就可以完全自定义一个页面。
CMSMgrDefaultListControl是默认的列表页面,在这个页面中要使用的Decorate组件,通过getDecorates获取所需要的组件,这个方法通常需要重载,从而按照结构返回所需要的组件。
createDecorateApps是根据getDecorates返回的结构创建实实在在的Gadget实例。
components函数是根据decorate标识,返回这个组件处理后的html片段。这个函数通常被视图tpl中反向调用,这样便于在视图中嵌入组件html片段。参见如下:
${p:("components","CMSMgrDefaultHeaderDecorate")}
《div class="row"》
《div class="col-xs-12"》
${p:("components","CMSMgrDefaultNodeDecorate")}
《/div》
《/div》
可见:
${p:("components","CMSMgrDefaultHeaderDecorate")}以及${p:("components","CMSMgrDefaultNodeDecorate")}
就是在页面片段中嵌入CMSMgrDefaultHeaderDecorate
,和CMSMgrDefaultNodeDecorate两个组件。
control数据
在Controler中除显示外,还有严密的数据处理,这个章节重点描述。数据请求也是定制重点,因为很多简单的定制跟数据相关。
在showcontent函数中处理函数关键的函数是processorShowData,这个processorShowData内部会按照顺序调用如下的几个函数:queryData-》handleMetaDataBefore-》handleDataBefore
最基本的是queryData,这个原始查询函数,其返回值是最原始的查询结果。其结构如下:
{
code:0,
data:{
cmsdata:[
{数据库中每条记录的值}
],
cmsmetadata:{
alias:"当前数据处理的别名",
ctypeid:"type的id,没有实际用处",
dataDesc:"对本数据结构的描述,这是关键字段",
displayName:"页面显示内容",
outAlias:"外部外联信息",
parentAlias:"挂接的节点,如果没有挂接,这里为空"
}
}
}
cmsmetadata里面的dataDesc是关键字段,这是模型管理中的字段描述,因为列表页和表单页面都是根据这个描述字段自动生成的。
queryData后面就会调用handleMetaDataBefore,就是在显示内容前,将进行一次处理,处理后会将cmsmetadata.dataDesc内容转成真正的json对象。其结构如下:
{
数据库中的字段:{
title:"显示的标题",
type:"显示字段类型",
fieldType:"数据库字段",
desc:"数据的描述",
.......其他字段
},
第二个字段......
}
每个字段实际都是模型定制时记录的描述填写的内容。
第三个处理函数handleDataBefore,这个是将获取的数据后进行的处理,其返回值如下:
[{数据库中每条记录的值}]
可见,其实这个就是原来原始数据结构的cmsdata。
最后的processorShowData创建的数据结构如下:
{
alias: 当前的alias,
data: handleDataBefore的返回数据,
metadata: handleMetaDataBefore,
titleData:标题数据,
orgData: 原始的查询返回的结果
titleData:标题数据,这是定制数据,不是标准数据
btnData:标题数据,这也是定制部分数据,不是标准数据
}
定制建议
页面定制很简单,一般只要重载定制Controler,如果页面变化很大,可以不用管原先的函数,直接重定义showContent,重新show。
更多的情况,可以重载Control下的任意一个子类,然后修改对应的视图中放置需要放置的组件。
我们会很快发布更多的组件。
另外,还有一种情况就是我们不用修改各种显示方法,而是修改里面的数据。其中有两种改法,一种是修改里面的数据,比如典型的,我们有个数据库字段存入的金额,而这个金额字段存入的分,但是在页面上显示的是元。这时就可以定制对应数据处理方法,将显示前将分改元。另外一种方式修改metadata,最典型的是,我们需要隐藏某个字段,这时就可以修改这个字段。
在定制时,定制的control都放到servicegadget中的xxxMgr目录下,对应自定义的资源文件也方法也一样放入其中。而外层框架可以自动扫描该目录下的内容并自动加载。