如何用JavaScript实现动态版权信息,避免UI初始化错误致页面崩溃
问题根源解析
你碰到的这个页面崩溃问题,罪魁祸首是**document.write()这个方法的特殊行为**:
- 当页面还在加载过程中调用它时,它会乖乖地把内容追加到当前文档流里,这就是为什么你第一次打开登录页时一切正常的原因。
- 但一旦页面已经完全加载完成(比如登出后导航回首页的场景),再调用
document.write()就会干一件很极端的事:清空整个已有的DOM文档,重新创建一个空白文档来写入内容。这直接把PrimeFaces布局依赖的所有结构(包括必须存在的center-pane元素)给彻底毁掉了,所以UI初始化时找不到必要的节点,就抛出了那个错误。
安全的替代实现方案
下面给你几种既能实现动态版权年份,又不会搞崩页面的方法:
方案1:服务器端直接生成年份(完全不用JS)
利用JSF的EL表达式,直接在服务器端获取当前年份,这种方式最稳妥,完全避免客户端脚本的问题:
<p:layoutUnit position="south" size="50" closable="true" collapsible="true"> Copyright @www.mycompany.com.br #{calendar.instance.get(Calendar.YEAR)} </p:layoutUnit>
如果你的项目没默认导入java.util.Calendar,只需要在faces-config.xml里加一行配置:
<application> <import>java.util.Calendar</import> </application>
方案2:用DOM安全操作替换document.write()
先给版权内容加个容器,然后用JS找到这个容器再修改内容,而不是覆盖整个页面:
<p:layoutUnit position="south" size="50" closable="true" collapsible="true"> <span id="copyright-content">Copyright @www.mycompany.com.br </span> <h:outputScript name="./script/currentDate.js" /> <script> // 等页面DOM加载完成后再执行 document.addEventListener('DOMContentLoaded', function() { document.getElementById('copyright-content').textContent += currYear(); }); </script> </p:layoutUnit>
顺便优化下你的currentDate.js,把过时的getYear()换成getFullYear()(getYear()已经被废弃,而且需要加1900才对,getFullYear()直接返回完整年份):
//<![CDATA[ function currYear() { return new Date().getFullYear(); } //]]>
方案3:适配PrimeFaces的AJAX场景(如果登出是AJAX触发)
如果你的登出操作是用AJAX实现的,那可以用PrimeFaces自带的jQuery来确保脚本在DOM就绪后执行:
<p:layoutUnit position="south" size="50" closable="true" collapsible="true"> <span id="copyright-content">Copyright @www.mycompany.com.br </span> <h:outputScript name="./script/currentDate.js" /> <p:outputScript> $(document).ready(function() { $('#copyright-content').append(currYear()); }); </p:outputScript> </p:layoutUnit>
最后提醒
document.write()在现代前端开发里已经属于不推荐使用的方法了,尤其是在使用像PrimeFaces这类组件框架时,它很容易破坏框架维护的DOM结构。上面的几种方案都能安全实现你的需求,再也不会出现登出后页面崩溃的问题啦。
内容的提问来源于stack exchange,提问作者Momergil
相关产品推荐
相关产品推荐

