转自:http://www.easyui.info/archives/279.html
熟悉Easyui的朋友可能都比较熟悉panel,因为panel是布局和其它一些组件的基础,在1.2.5版本中,panel的标题部分增加了对工具条的支持(1.2.4可能也支持,但是不支持写在HTML文档中的工具条)。
现象描述:
给panel附加工具条有两种方式:
Name | Type | Description | Default |
---|---|---|---|
tools | array,selector | Custom tools, possible values: 1) an array, each element contains iconCls and handler properties. 2) a selector that indicating the tools | [] |
- 一种是定义数组数据,数组每个对象包含iconCls和handler属性,分别用于图标和事件;
- 另一种就是类似css选择器的字符串形式,Easyui会根据这个字符串到当前页面找字符串表达式选取到的DOM,将其作为panel的tools:
对于第一种方式,申明javascript数组对象,肯定是可以实现多个panel共用一个数组对象的;对于第二种方式就不尽如人意了,一个源tools只能被一个panel使用。个人觉得第二种方式源tools只能被一个panel使用是不合理的,有时候我们很有可能多个panel共用一个tools,而且写在HTML里面更直观,所以第二种方式的tools需要改进。
源码分析:
我们来分析一下生成panel标头部分的源码:
function _173(_174){
var opts = $.data(_174, "panel").options;
var _175 = $.data(_174, "panel").panel;
if (opts.tools && typeof opts.tools == "string") {//注释掉这句往下三行
_175.find(">div.panel-header>div.panel-tool .panel-tool-a").appendTo(opts.tools);
}
_165(_175.children("div.panel-header"));
if (opts.title && !opts.noheader) {
var _176 = $("<div class=\"panel-header\"><div class=\"panel-title\">" + opts.title + "</div></div>").prependTo(_175);
if (opts.iconCls) {
_176.find(".panel-title").addClass("panel-with-icon");
$("<div class=\"panel-icon\"></div>").addClass(opts.iconCls).appendTo(_176);
}
var tool = $("<div class=\"panel-tool\"></div>").appendTo(_176);
if (opts.tools) {
if (typeof opts.tools == "string") {//如果是字符串,也就是我说的第二种方式
$(opts.tools).children().each(function(i){
/**
* 这个地方是不能重用的根本原因,因为jQuery的appendTo方法破坏性操作,即源DOM被移动到目标位置,而不是拷贝到目标位置。
* 所以作为源的tools只要被一个panel使用就等于被empty()了,当然也就无法被多个panel同时使用了,
* 知道原因就知道改怎么改进了,应该使用clone的方式拷贝,直接使用jQuery的clone()方法拷贝即可.
* 克隆拷贝之后还要注意到,地4-6行代码,如果当前panel中已经存在一些tool,则会把这些tool移动到源tools中,然后清空panel内部tool。
* 使用克隆拷贝后,4-6行的代码就不再需要了,4-6行代码是为了备份已有tool,而现在不需要备份了,再备份的话会造成重复的源tools
*/
$(this).addClass($(this).attr("iconCls")).addClass("panel-tool-a").appendTo(tool);
});
}
else {
for (var i = 0; i < opts.tools.length; i++) {
var t = $("<a href=\"javascript:void(0)\"></a>").addClass(opts.tools[i].iconCls).appendTo(tool);
if (opts.tools[i].handler) {
t.bind("click", eval(opts.tools[i].handler));
}
}
}
}
if (opts.collapsible) {
$("<a class=\"panel-tool-collapse\" href=\"javascript:void(0)\"></a>").appendTo(tool).bind("click", function(){
if (opts.collapsed == true) {
_18e(_174, true);
}
else {
_183(_174, true);
}
return false;
});
}
if (opts.minimizable) {
$("<a class=\"panel-tool-min\" href=\"javascript:void(0)\"></a>").appendTo(tool).bind("click", function(){
_194(_174);
return false;
});
}
if (opts.maximizable) {
$("<a class=\"panel-tool-max\" href=\"javascript:void(0)\"></a>").appendTo(tool).bind("click", function(){
if (opts.maximized == true) {
_197(_174);
}
else {
_182(_174);
}
return false;
});
}
if (opts.closable) {
$("<a class=\"panel-tool-close\" href=\"javascript:void(0)\"></a>").appendTo(tool).bind("click", function(){
_177(_174);
return false;
});
}
_175.children("div.panel-body").removeClass("panel-body-noheader");
}
else {
_175.children("div.panel-body").addClass("panel-body-noheader");
}
};
代码修正:
要分析的内容均已经写在代码的注释里面了,所以最后的该法只要进行以下改动即可:
- 要将4-6行代码注释掉
- 将each循环内部appendTo之前先clone元素
clone的写法如下:
if (typeof opts.tools == "string") {
$(opts.tools).children().each(function(i){
$(this).addClass($(this).attr("iconCls")).addClass("panel-tool-a").clone().appendTo(tool);
});
}