项目里面有个页面,包含一个tabs,共有六个tab标签,每个标签里面都有一个datagrid,除此之外,页面里面还有若干dialog。
发现弊端
这个页面加载非常慢,原因就是该页面会在所有组件全部渲染完成才显示,这样非常影响性能,因为有的组件完全可以在需要用的时候才去渲染。
单例模式封装组件
主要常用form,dialog,datagrid组件,如下简单进行封装(以datagrid举例)。
最简单的封装
function datagrid(selector,options){
// 原datagrid的引用
this.datagrid = null;
this.init = function (){
if(null == this.datagrid){
// 初始化,大概代码如下
this.datagrid = $(selector).datagrid(options);
}
return this;
}
}
datagrid.prototype.invoke = function (method,params){
// 确保已经初始化
this.init();
// 调用方法,如下写法为了方便链式调用
var result = this.datagrid.datagrid(method,params);
if(result == this.datagrid){
return this;
}
return result;
}
然后,项目里的代码就可以改成这样了
// 先声明一个datagrid
var dg = new datagrid('#dg',{
// 这里是原本datagrid的参数
url:'',
columns:[[]],
});
然后在 tabs 组件的 onSelect 事件里写如下代码
onSelect:function(title,index) {
// 根据标签index去调用对应datagrid的初始化方法
if(0 == index){
dg.init();// 这样保证在切换到该标签时才会去渲染对应的组件
}
}
这样就保证了在一开始进入页面的时候不会去初始化一些暂时不需要的组件,提高了性能。
因为我没在官网上看到datagrid有添加行的事件,这就导致有个地方很蛋疼了。
比如我要在添加一条数据之前进行判断是否有已经存在的行跟要添加的行有若干字段是相等的, 如有则取消本次添加的操作。
你会说,那你就在调用 appendRow 之前判断咯。
当然,如果我只有一个地方调用 appendRow ,那确实没什么,但如果有超过一个地方会调用呢?而且这理论上应该是在事件里去检测的。
所以,上面的封装就体现了另一个好处了,可以添加事件!!!
封装前我要添加一行是这么写
var dg = $('#dg').datagrid({options});
dg.datagrid('appendRow',row);
封装后呢
var dg = new datagrid('#dg',options);
dg.invoke('appendRow',row);
我只要在invoke里对 method 参数进行判断,如果是 appendRow ,就去调用对应的我定义的 onAppendRow方法,如果返回false,我就不调用appendRow方法即可。