为什么document.write被认为是“不好的做法”?
我知道document.write
被认为是不好的做法; 我希望编写一份列表,向第三方供应商提交他们为什么不应该在他们的分析代码的实现中使用document.write
。
请将您的理由声明为document.write
作为一个糟糕的做法下面。
一些更严重的问题:
-
document.write(从此DW)在XHTML中不起作用
-
DW不直接修改DOM,防止进一步的操作(试图find这个证据,但它是最好的情况下) -
在页面加载完成后执行DW会覆盖页面,或者写一个新页面,或者不行
-
DW执行遇到的地方:它不能注入给定的节点
-
DW有效地编写了序列化的文本,这不是DOM在概念上工作的方式,而且是一个简单的方法来创build错误(.innerHTML有同样的问题)
最好使用安全和DOM友好的DOM操作方法
document.write
实际上没有错,本身。 问题在于滥用它真的很容易。 大体上,甚至。
就提供分析代码的供应商而言(比如Google Analytics),实际上这是他们分发此类代码段的最简单的方法
- 它保持脚本小
- 他们不必担心重写已经build立的onload事件或包括必要的抽象来安全地添加onload事件
- 这是非常兼容的
只要你没有在文件加载之后尝试使用它, document.write
就不是天生就是邪恶的。
document.write
另一个合法使用来自HTML5 Boilerplate index.html示例。
<!-- Grab Google CDN's jQuery, with a protocol relative URL; fall back to local if offline --> <script src="//ajax.googleapis.com/ajax/libs/jquery/1.6.3/jquery.min.js"></script> <script>window.jQuery || document.write('<script src="js/libs/jquery-1.6.3.min.js"><\/script>')</script>
我也看到了使用json2.js JSONparsing/string化填充 ( IE7和以下需要 )的相同技术。
<script>window.JSON || document.write('<script src="json2.js"><\/script>')</script>
它可以阻止你的网页
document.write
只在页面加载时才起作用; 如果在页面加载完成后调用它,它将覆盖整个页面。
这实际上意味着你必须从内联脚本块调用它 – 这将阻止浏览器处理后续页面的部分内容。 在写入块完成之前,脚本和图像将不会被下载。
优点:
- 从外部(到主机/域)脚本embedded内容是最简单的方法。
- 您可以覆盖帧/ iframe中的全部内容。 在更现代的Ajax技术被广泛使用之前(1998-2002),我曾经习惯使用这种技术来进行菜单/导航部分。
缺点:
- 它序列化渲染引擎暂停,直到外部脚本加载,这可能比内部脚本花费更长的时间。
- 通常使用脚本放在内容中,这被认为是不好的forms。
这里是我的两个价值,一般来说你不应该使用document.write
来举重,但是有一个实例肯定是有用的:
http://www.quirksmode.org/blog/archives/2005/06/three_javascrip_1.html
我最近发现这个试图创build一个AJAX滑块库。 我创build了两个嵌套的div,并应用width
/ height
和overflow: hidden
到JS的外部<div>
。 这是因为,如果浏览器禁用JS,div将浮动以适应图库中的图像 – 一些不错的降级。
事情就像上面的文章一样,这个JS劫持的CSS没有启动,直到页面加载,造成一个瞬间的闪光,因为div被加载。 所以我需要写一个CSS规则,或者加载一个页面。
显然,这在XHTML中不起作用,但是由于XHTML看起来像是一个死鸭(在IE中呈现为标签汤),可能值得重新评估您对DOCTYPE的select。
它使用XML呈现中断页面(如XHTML页面)。
最佳 :一些浏览器切换回HTML渲染,一切正常。
可能 :某些浏览器在XML呈现模式下禁用document.write()函数。
最糟糕的是 :一旦使用document.write()函数,一些浏览器就会触发一个XML错误。
它覆盖页面上的内容是最明显的原因,但我不会把它称为“坏”。
它只是没有太大的用处,除非你使用JavaScript创build一个完整的文档,在这种情况下,你可以从document.write开始。
即使如此,当你使用document.write的时候,你并没有真正利用DOM–你只是将一些文本转储到文档中,所以我认为这是糟糕的forms。
closures我的头顶上:
-
document.write
需要在页面加载或主体加载中使用。 所以如果你想在其他任何时候使用这个脚本来更新你的页面内容document.write几乎是没用的。 -
从技术上讲,
document.write
只会更新HTML页面而不是XHTML / XML。 IE似乎是相当宽容的这个事实,但其他浏览器不会。
可以将document.write()(和.innerHTML)看作是评估源代码string。 这对于许多应用程序来说非常方便。 例如,如果您从某个源获取HTML代码作为string,则只需“评估”它即可。
在Lisp的上下文中,DOM操作就像操作列表结构,例如通过执行以下操作来创build列表(橙色):
(cons 'orange '())
和document.write()就像评估一个string,例如通过评估一个源代码string像这样创build一个列表:
(eval-string "(cons 'orange '())")
Lisp还具有使用列表操作创build代码的非常有用的function(如使用“DOM样式”创buildJS分析树)。 这意味着你可以使用“DOM风格”而不是“string风格”build立一个列表结构,然后运行该代码,例如:
(eval '(cons 'orange '()))
如果您实现编码工具,比如简单的实时编辑器,那么能够快速评估一个string非常方便,例如使用document.write()或.innerHTML。 Lisp在这个意义上是理想的,但是你也可以在JS中做很酷的东西,很多人都这样做,比如http://jsbin.com/
document.write的缺点主要取决于这三个因素:
a)实施
document.write()主要用于在需要内容时立即将内容写入屏幕。 这意味着它发生在任何地方,无论是在JavaScript文件或HTML文件内的脚本标签内。 将脚本标签放置在这样一个HTML文件中的任何位置,在web页面内与HTML交织的脚本块中放置document.write()语句是一个坏主意。
b)渲染
一般而言,精心devise的代码将采取任何dynamic生成的内容,将其存储在内存中,并在代码通过代码之前继续对其进行操作,然后才能将其释放到屏幕上。 因此,为了重申前一节中的最后一点,就地呈现内容可能会比其他可能依赖的内容呈现得更快,但是其他代码可能无法使用其他代码,而这些代码又需要呈现内容以供处理。 为了解决这个困境,我们需要摆脱document.write()并以正确的方式实现它。
c)不可能的操作
一旦写完了,就完成了。 我们不能回去操纵它,而不需要进入DOM。
Chrome可能会阻止在某些情况下插入脚本的document.write
。 发生这种情况时,它将在控制台中显示此警告:
通过document.write调用parsing器,交叉源脚本…。 如果设备networking连接不好,可能会被浏览器阻止。
参考文献:
- 这篇关于developers.google.com的文章更详细。
- https://www.chromestatus.com/feature/5718547946799104
-
document.write
是一个不好的做法的一个简单的理由是,你不能想出一个场景,你不能find一个更好的select。 - 另一个原因是你正在处理string而不是对象(这是非常原始的)。
- 它只附加到文档。
- 它没有例如MVC(模型 – 视图 – 控制器)模式的美感。
- 使用ajax + jQuery或者angularJS呈现dynamic内容更加强大。
我认为最大的问题是,通过document.write写入的任何元素都被添加到页面元素的末尾。 这很less是现代页面布局和AJAX的理想效果。 (你必须记住,DOM中的元素是暂时的,当脚本运行时可能会影响它的行为)。
最好在页面上设置一个占位符元素,然后操作它的innerHTML。