<html>
<head>
<title>HTML5_插入标记</title>
<meta charset="utf-8">
<script type="text/javascript">
window.onload = function(){
/*
虽然DOM为操作节点提供了细致入微的控制手段,但在需要给文档插入大量新HTML标记
的情况下,通过DOM操作仍然麻烦,因为不仅创建一系列的DOM节点,而且还要小心按
正确的顺序连接起来。相对而言,使用插入标记技术,直接插入HTML字符串不仅更加
简单,速度也更快。以下与插入标记相关的DOM扩展已经纳入HTML5规范。
1、innerHTML属性
在读模式下,innerHTML属性返回与调用元素的所有子节点(包括元素、注释文本节点)
对应HTML标记。在写模式下,innerHTML会根据指定的值创建新的DOM树,然后这个DOM
树完全替换调用元素原先的子节点。下面是一个例子。
<div id = "content">
<p>This is a <strong>paragraph</strong>with a list following it.</p
<ul>
<li>Item 1 </li>
<li>Item 2 </li>
<li>Item 3 </li>
</ul>
</div>
对于上面的<div>元素来说,它的innerHTML属性会返回如下字符串。
<p>This is <strong>paragraph</strong>with a list following it.</p>
<ul>
<li>Item 1</li>
<li>Item 2</li>
<li>Item 3</li>
</ul>
但是不同的浏览器返回的文本格式会有所不同。IE和Opera会将所有的标签转换为大写
形式,而Safari Chrome 和firefox会原原本本按照原先的文档中(或指定这些标签时)
的格式返回HTML,包括空格和缩进。不要指望所有的浏览器返回的innerHTML值完全相同。
在写的模式下,innerHTML的值会被简析为DOM子树,替换调用元素原来所有的子节点。
因为它的值被认为是HTML,所以其中所有的标签都会按照浏览器处理HTML的标准方式转换
元素(同样这里的转换结果也因浏览器而异)。如果设置的值仅是文本而没有HTML标签,那
么结果就是设置纯文本,如下所示。
div.innerHTML = "Hello world!";
为innerHTML设置的包含HTML的字符串值与解析或innerHTML的值大不相同。来看下面的例子。
div.innerHTML = "Hello & welcome,<b>\"reader\"!</b>";
以上操作得到的得到的结果如下:
<div id = "content">Hello & welcome, <b>"reader"!</b></div>
*/
document.querySelector("#myDiv").innerHTML = "Hello & welcome,<b>\"reader\"!</b>";
alert(document.querySelector("#myDiv").innerHTML);
/*
设置innerHTML之后,可以像访问文档中的其他节点一样访问创建节点。
使用innerHTML属性也有一些限制。比如大多数浏览器中通过innerHTML插入<script>
元素并不会执行其中的脚本。IE8及更早的版本是唯一能在这种情况下执行脚本的浏览
器,但必须满足一些条件。一是必须为<script>元素指定defer属性,二是<script>元素
必须位于(微软所谓的)有作用域的元素(scoped element)之后。<script>元素被认为
是无作用域的元素(NoScope element),也就是在页面中看不到元素,与<style>元素注释
类似。如果通过innerHTML插入的字符串开头就是一个无作用域的元素,那么IE会在解析这
个字符串前先删除这个元素。换句话说,以下代码达不到目的:
div.innerHTML = "<script defer>alert('hi');</\script>";//无效
此时,innerHTML字符串一开始(而且整个)就是一个无作用域的元素,所有这个字符串
会变成空字符串。如果想插入这段脚本,必须在前面添加一个“有作用域的元素”,可以是一个
文本节点也可以是一个没有结束标签的的元素如<input>。
例如下例代码可以正常执行:
div.innerHTML = "_<script defer>alert('hi');<\/script>";
div.innerHTML = "<div> </div><script defer>alert('hi');<\/script>";
div.innerHTML = "<input type = \"hidden\"><script defer>alert('hi')<\/script>";
第一行代码会在<script>元素前插入一个文本节点。事后,为了不影响页面显示,你可能
需要移除这个文本节点。第二行代码采用的方法类似,只不过使用的是一个非换行符空格
的<div>元素。如果仅仅插入一个空的<div>元素,还是不行;必须包含一点儿内容,浏览器
才会创建文本节点。同样,为了不影响页面布局,恐怕还得移除这个节点。第三行代码使用
一个隐藏的<input>域,也能达到相同的效果。不过由于隐藏的<input>域不影响页面布局,
因此这种方式是大多数情况的首选。
大多数浏览器都支持以直观的方式通过innerHTML插入<style>元素,例如:
*/
var myStyle = document.querySelector("#myStyle");
myStyle.innerHTML = "<style type=\"text/css\">body{background-color:gray;}<\/style>";
/*
但在ie8及更早的版本,<style>也是没有作用域的元素,因此必须向下面给他前置一个有作用域
的元素:
*/
myStyle.innerHTML = "_<style type = \"text/css\">body{background-color:green;}<\/style>"
myStyle.removeChild(myStyle.firstChild);
/*
并不是所有的元素都支持innerHTML属性。不支持innerHTML的元素有:<col>、<colgroup>、
<frameset>、<head>、<html>、<style>、<table>、<tbody>、<thead>、<tfoot>和<tr>。此外,
在IE8及更早的版本中,<title>元素也没有innerHTML属性。
无论什么时候,只要用innerHTML从外部插入HTML,都应该首先以可靠的方式处理HTML。IE8为此
提供了window.toStaticHTML()方法,这个方法接收一个参数,即一个HTML字符串;返回一个经过
无害处理的版本--从源HTML中删除所有的节点脚本和事件处理程序属性。
下面是一个例子:
var text = "<a href=\"#\" onclick =\"alert('hi')\">Click Me</a>";
var sanitized = window.toStaticHTML(text);//仅有ie支持,会删除onclick =\"alert('hi')代码。
alert(sanitized);
2、outerHTML属性
在读模式下outerHTML,返回调用它的元素及所有子节点的HTML标签。在写模式下,outerHTML
会根据指定的HTML字符串创建新的DOM子树,然后用这个DOM子树完全替换调用元素。下面是
一个例子。
<div id ="content">
<p>This is a<strong>paragraph</strong> with a list following it.</p>
<ul>
<li>Item 1</li>
<li>Item 2</li>
<li>Item 3</li>
</ul>
</div>
如果在<div>元素上调用outerHTML,会返回上面相同的代码,包括<div>本身。不过由于
浏览器解析和解释HTML标记不同,结果也可能有所不同。(这里的不同与使用innerHTML属性
时存在的差异性质是一样的。)
使用outerHTML以下面这种方式设置值:
div.outerHTML = "<p> p tag replace div tag</p>";
这行代码完成操作与下面的DOM脚本代码一样:
var p = document.createElement("p");
p.appendChild(document.createTextNode("p tag replace div tag"));
div.parentNode.replaceChild(p,div);
结果就是新建<p>元素去替换原来的<div>元素。
支持outerHTML属性的浏览器有IE4+、Safari4+、Chrome和Oprea 8+。firfox 7及之前的版本
都不支持outerHTML属性。
3、insertAdjacentHTML()方法
插入标记的最后一新增方式是insertAdjacentHTML()方法。这个方法最早也是在IE中出现的,
它接收了两个参数:插入位置和要插入的HTML文本。第一参数必须是下列的值之一。
beforebegin:在当前的元素之前插入一个紧邻的同辈元素;
afterbegin:在当前的元素之下插入一个新的子元素或者第一个元素之前再插入一个
新的元素;
beforeend:在当前元素之下再插入一个新的子元素或者在最后一个子元素再插入一个
新的元素;
afterend,在当前元素之后插入一个紧邻的同辈元素。
注意,这些值都必须是小写形式。第二个参数是一HTML字符串(与innerHTML和outerHTML
值相同)如果浏览器无法解析该字符串,就会抛出错误。以下是这种方法的基本示例。
//作为前一个同辈插入
element.inserAdjacentHTML("beforebegin","<p>Hello world!</p>");
//作为第一个元素插入
element.insertAdjacenHTML("afterbegin","<p>Hello world!</p>");
//作为最后一个子元素
element.insertAdjacenHTML("beforeend","<p>Hello world!</p>");
//作为后一个同辈元素插入
element.insertAdjacenHTML("afterend","<p>Hello world!</p>");
支持insertAdacenHTML()方法的浏览器IE、Firefox 8+、Safari、Opera 和Chrome。
4、内存与性能问题
使用replaceChild替换子节点的方法可能会导致浏览器内存占用问题,尤其是在IE中
问题更加明显。在删除带有事件删除程序或引用了其他JavaScript对象子树时,就有可能
导致内存占用的问题。假设某个元素有事件处理程序(或者引用其他的JavaScript对象树)
在使用前叙某个元素从文档中删除后,元素与事件处理程序(或者javaScript对象)之间
绑定关系在内存中并没有一并删除。如果这种情况频繁出现,页面占用的内存数量就会明
显增加。因此,在使用innerHTML、outerHTML属性和insertAdjacentHTML()方法时。最后
先手工删除要被替换的元素的所有事件处理程序和JavaScript对象属性。
不过使用几个属性 特别是innerHTML,仍然可以给我提供很多的便利。一般来说插入
大量新的HTML标记时,使用innerHTML属性与通过多次DOM操作创建节点再指定他们之间的
关系来说,效率要高得多。这是因为使用innerHTML和outerHTML时,就会创建一个HTML解
析器。这个解析器是浏览器级别的代码(通常是C++)基础上运行的,因此比执行javaScript
快得多。不可避免地,创建和销毁HTML解析器也带来性能损失,所有最后把使用innerHTML
和outerHTML的使用此时控制在合理的范围内,即能拼接长的HTML串一次给innerHTML赋值的
情况下就一次赋值,而不去每添加一个元素就给innerHTML赋值。
*/
}
</script>
</head>
<body>
<div id="myDiv" data-appId="314145" data-myName = "神经病"></div>
<div id="myStyle"></div>
</body>
</html>
HTML5_插入标记
最新推荐文章于 2022-03-09 16:49:53 发布