最近做了一个单页面的网站,所有的页面加载都是通过局部刷新的方式,并且不用iframe,并且我们引入了动态tab页签:
所有的页签里的内容都只是一个元素,都在同一个html页面上,没有任何iframe分割,这样遇到了一个非常突出的问题——页面复用。
页面复用会遇到什么问题?
假设在A标签页和B标签页用的是同一个jsp,就像上图的两个【字典编辑】页签,里面的内容用的是同一个jsp,那么这个jsp里面的js方法名、js变量名、页面元素id都会冲突。
冲突带来一些列问题,给表单绑定方法的时候不知道实际是给哪个表单绑定的方法,表单提交完后刷新的不知道是哪个div,刷新的是哪个树等等等等。
通过一番尝试和折磨找到了以下几个解决办法(如果再给我个机会重做的话,我一定会放弃动态多标签):
1、每打开一个tab签都会在后台生成一个不会重复字符串【idPrefix】放在session里,例如(_33ae9d282966409b9c9c041fb93aa596_),然后在变量和id命名时通过el表达式将idPrefix作为他们的前缀,如下:
//js变量命名 var ${idPrefix}sysDictTree;//树对象; var ${idPrefix}selectDictNode; //js方法变量命名 function ${idPrefix}reloadDictNodes(){ } //dom元素id命名 <div class="col-md-9" id="${idPrefix}dictItemNodeDetail"></div>
因为是jsp所以可以在前面加个${idPrefix},姑且不考虑这个工作量和开发复杂度,如果每一个tab页签中的内容都是一次性打开的,那么这样做已经可以解决。
但是,像上图这样的左边一个树右边一个表单的情况,这就会引发一个问题:
我先打开了A的字典编辑,这个时候idPrefix假设是A1,然后我再打开B的字典编辑,idPrefix已然被换掉了,假设变成了B1,
此时我回头来操作A的树,点击了某个叶子节点,右边加载了一个表单AForm,
然后操作B的树,点击某个叶子节点右边加载了一个BForm,
AForm和BForm用的是同一个jsp,那么此时AForm和BForm里的${idPrefix}是一样的,带来的结果是他们仍然会产生冲突,这个时候怎么办?
对于这种同一个tab签上的内容,不是一次性加载的,我又做了这样一个改进:
2、虽然AForm和BForm的id、js变量、js方法名是一毛一样的,但是他们位于不同的tab签中,并且我们的tab签有一个特点,某一个时刻只有一个tab签是激活(active)的,
那么我们在js里面为Form本身或者Form里的某个id的元素绑定事件或者直接操作他们的时候,我们可以获取当前激活的tab签中的某个元素,因为我们只有打开(激活)某个页签才能操作里面的东西,所以在这里【当前】和【现在被激活的】tab签是同一个。用代码来表示就是:
Addtabs.getCurrentTabElementById("${idPrefix}dictNodeForm").validate({
rules: {
TEXT: {
required: true
},
VALUE: {
required: true
},
IS_USE: {
required: true
},
SEQ: {
required: true,
digits: true
}
}
);
其中的
Addtabs.getCurrentTabElementById
就代表获取当前激活的。
这个时候第三个问题也来了,如果我想提交完这个表单,然后去刷新当前tab签上的树,我怎么知道那个树的id是什么,或者如果那个树已经放在某个变量里了我怎么知道那个变量的变量名?
3、我的做法是在我们加载某个tab页签的时候,把idPrefix存放在tab签的内容div的属性当中,因为树和div是一起加载的,所以这个属性里的idPrefix和树的肯定一致,我只需要在js中获取当前tab签的内容div里的该属性即可,然后:
eval("pnode="+tabIdPrefix+"sysDictTree.getNodeByParam('id',pid)");
通过eval来执行拼接的js即可。
暂且就这三个措施,非常复杂,其它问题遇到再解决吧。。