在JSP裏混用JSF元件與HTML/JavaScript,輸出到Client時(shí)會(huì)被分離之迷解答
開(kāi)發(fā)JSF頁(yè)面及元件這半年來(lái),常遇到一個(gè)問(wèn)題,
在JSF的頁(yè)面裏,混著寫(xiě)html/javascript文字及元件tag時(shí),
輸出結(jié)果在最後output到client端時(shí)有時(shí)會(huì)被分離成兩組輸出,
而不是以我們?cè)贘SP看到的順序輸出。
例如一:
<ui:Panel id="panel">
<div>
<script>alert("A")</script>
<ui:Button id="button"/>
</div>
</ui:Panel>
期望在client端應(yīng)該是,
<div id="form1:panel>
<div>
<script>alert("A")</script>
<input type="button" id="form1:button"/>
</div>
</div>
但事實(shí)上會(huì)變成
<div>
<script>alert("A")</script>
</div>
<div id="form1:panel>
<input type="button" id="form1:button"/>
</div>
這個(gè)列子在初步一看一定覺(jué)得不合理,
而且在實(shí)際的開(kāi)發(fā)上,一定會(huì)產(chǎn)生困優(yōu)。
但這件事經(jīng)過(guò)最終看完source後,又覺(jué)得無(wú)可厚非
會(huì)發(fā)生這件事情的主要元因是JSF的架構(gòu)性的問(wèn)題...
當(dāng)你使用的元件是一個(gè)Container時(shí)(例如Panel這類(lèi)的元件)
他可能會(huì)期望自己來(lái)排列兒子的順序(例如grid layout)
而不是依tag寫(xiě)的"單純"順序去輸出結(jié)果。
這時(shí)候,這顆元件會(huì)(應(yīng)該)去改寫(xiě)getRenderChildren(),並retrun true,表示他要自己來(lái)render兒子.
(以gridPanel來(lái)看,就必需在各個(gè)兒子間用tr/td來(lái)作排版)
即表示,這時(shí)候利用的JSP裏tag的順序來(lái)out是不合用的,
因?yàn)閠ag跟tag中間可能要有其parent的客制化輸出
從JSF規(guī)格的source(UIComponentTag)來(lái)看
當(dāng)一個(gè)元件不用自己render兒子元件時(shí),
他的encodeStart會(huì)在doStartTag被呼叫
他的encodeEnd會(huì)在doEndTag被呼叫
他其兒子就理所當(dāng)然的依JSP裏tag執(zhí)行的順序被呼叫到,(而不呼叫該元件的encodeChildren)
而穿插在tag中的純文字輸出就理所當(dāng)然依順序被輸出
例如JSP的JAVA Code:
panel_tag.doStartTag()
out.write("<div>")
out.wirte("<script>alert(\"A\")</script>");
button_tag.doStartTag();
button_tag.doEndTag();
out.write("</div>");
panel_tag.doEndTag();
可是當(dāng)一顆元件需要自己render兒子元件時(shí)
元件會(huì)設(shè)定了一個(gè)suppressed falg,(還有其他狀況的設(shè)suppressed,列如這個(gè)元件是在facet裏)
則它的encodeStart,encodeChildren及encodeEnd就會(huì)只在doEndTag時(shí)被呼叫(UIComponentTag的實(shí)作)
從這個(gè)元件之後.
它的所有下層元件將被壓制,不再在doStartTag,及doEndTag裏來(lái)輸出,
而這顆元件有將其下層元件呼叫輸出的義務(wù)(直到遇到下層中另外一顆也需自己輸出兒子的元件)。
從JSP的JAVA CODE來(lái)看.
panel_tag.doStartTag() ==> no output
out.write("<div>")
out.wirte("<script>alert(\"A\")</script>");
button_tag.doStartTag(); ==> no output
button_tag.doEndTag(); ==> no output
out.write("</div>");
panel_tag.doEndTag(); ==> out panel & button
很明顯的,將導(dǎo)致輸出被分離的結(jié)果。
結(jié)論是,當(dāng)一個(gè)頁(yè)面用了類(lèi)似Panel這種要自己layout children的Componet後,
在裏面寫(xiě)的HTML或javascript,必需不包含位置及序頁(yè)的特性
也就是說(shuō)JavaScript寫(xiě)成在.js裏,HTML....應(yīng)該是沒(méi)救了...不要寫(xiě)HTML~~~
Or,請(qǐng)愛(ài)用Tiles Panel元件~~~~~將script及html寫(xiě)在tiles對(duì)應(yīng)的layout.jsp裏
posted on 2007-07-12 16:53
冰封的愛(ài) 閱讀(862)
評(píng)論(0) 編輯 收藏 所屬分類(lèi):
J2EE