最近做了一個單頁面的網站,所有的頁面加載都是通過局部刷新的方式,並且不用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即可。
暫且就這三個措施,非常復雜,其它問題遇到再解決吧。。