這是個小菜在實際工作中遇到的問題,相信很多EasyUI新手很可能也遇到這樣的問題,因此小菜覺得有必要拿出來分享一下。
這個問題要從EasyUI的datebox組件說起,小菜用這個組件的時候,發現用$("#id").val()這種形式,居然拿不到文本框的值!
經過度娘的幫助,發現可以用$("#id").datebox('getValue'),但是這是為什么捏?
經過一翻研究和探索,小菜發現,如果一個input加上class="easyui-datebox",也就是聲明在此文本框上邊使用datebox組件,那么經過EasyUI引擎的掃描,會自動為此文本框加上各種樣式,與此同時,EasyUI去掉了此文本框上的id和name屬性!最后,它會在此文本框的附近,添加一個隱藏的文本框,這個文本框的name和原來文本框的name一樣,id屬性直接丟掉。。。。這個隱藏文本框的值,才是咱們看到的日期。如圖:
這下讀者應該明白,為什么$("#id").val()拿不到值,因為原來文本框的id屬性已經被拿掉,新創建的隱藏文本框也沒有id屬性,所以拿不到值,可以通過官方的給出的$("#id").datebox('getValue')彌補(具體人家怎么拿到的,小菜也不懂呀)。
但是,這僅僅是用id選擇器的情況,別忘了還有name,我們可以通過$("input[name='mydate']").val()這種方式獲取文本框的值。
因此,如果不想用$("#id").datebox('getValue'),那么就別加id,或者說別用id選擇器,給文本框加一個name屬性,很輕松的就拿到值了。
另外,補充一下,如果用的標簽選擇器,也就是用的name屬性,然后又用.datebox('getValue')去拿值,那么會報錯哦。。。例如:$("input[name='mydate']").datebox('getValue'),會報TypeError: $.data(...) is undefined。
說了這么多,貌似還沒有進入正題,讀者應該也能體會到,在某個input標簽上添加class="easyui-datebox",它就能自動變成日歷,這其實是EasyUI掃描的結果,在網頁加載完成后,相當於在$(document).ready()事件中,對整個網頁進行了一次掃描,發現某個input標簽含有class="easyui-datebox"屬性,就做上邊講到那些處理,不僅僅是EasyUI如此,幾乎所有的UI都是這個原理。
因此,如果我們用什么append、appendTo方法動態在頁面中插入一段html代碼,或者用什么addClass方法給input標簽動態添加一個class屬性,這些操作EasyUI是不知道的,所以新插入的這些東東,即使有class="easyui-datebox"屬性,但沒有任何效果。
如何通知EasyUI呢?通過查詢資料,發現網上比較流行的一種方法是用:$.parser.parse()。一般像我這樣的小菜可能就直接拿來用了,把它放在插入html的語句之后,重新渲染界面,果然很管用,新加入的元素能被識別。
但是,小菜很快就發現一個問題,由於使用了$.parser.parse()對整個頁面重新渲染,這會影響到以前已經渲染過的組件。
舉個例子:頁面原本有一個使用了datebox組件的input標簽,用戶通過datebox組件選擇了時間,然后用戶又新增了一個使用datebox組件的input標簽(這時候程序會重新渲染頁面),奇怪的事情發生了:原來的input標簽明明已經選過時間,顯示的也正常,但卻拿不到值!
根據小菜的想法,原因正是出在$.parser.parse()上,由於它對整個頁面進行渲染,以前正常的組件也被渲染了,相當於所有的組件進行了一次“初始化”,最終導致值丟失。
再仔細問問度娘,發現$.parser.parse()是可以帶參數的,參數意思差不多就是傳入一個局部的DOM對象,只對局部進行渲染,避免影響其他組件。
舉個巧妙的應用例子:
var targetObj = $("<input name='mydate' class='easyui-datebox'>").appendTo("#id");
$.parser.parse(targetObj);
我們常常會通過appendTo方法把使用了datebox組件的input標簽插入到某個DOM中,別忘了appendTo方法是有返回值的,返回的恰恰就是剛剛插入的對象。我們拿到這個對象,單獨對它進行渲染,這樣既可以實現動態渲染,又能避免影響其它組件。
因此,在讀者的項目中,最好使用局部渲染(無論用何種方法得到目標對象),避免使用全局渲染。
好啦,小菜的教程就寫到這,希望對大家有所幫助,高手勿噴~