你的位置:首页 > Java教程

[Java教程]DOM中文本和标记的插入


innerHTML

  innerHTML在读模式下,返回与调用元素的所有子节点(包括元素、注释和文本节点)对应的HTML标记。在写模式下,innerHTML会根据指定的值创建新的DOM树,然后用这个DOM树完全替换调用元素原先的所有子节点。

  [注意]并不是所有元素都支持innerHTML属性,不支持innerHTML的属性有:<col>、<colgroup>、<frameset>、<head>、<html>、<style>、<table>、<tbody>、<thead>、<tfoot>、<tr>。在IE8-浏览器中<title>元素也没有该属性

<ul id="list">  <li >1</li>  <li >2</li>  <li >3</li></ul>  <script>//IE8-浏览器会将所有标签转换成大写形式,且不包含空白文本节点;而其他浏览器则原样返回var oList = document.getElementById("list");console.log(oList.innerHTML);</script>

  

  [a]如果设置的值只是文本,则结果就是设置纯文本

<div id="box"></div><script>var oBox = document.getElementById("box");oBox.innerHTML = "hello world!";//页面显示hello world!</script>

  [b]如果设置的值包含HTML标签,则浏览器会将这个字符串解析成相应的DOM树

<div id="box"></div><script>var oBox = document.getElementById("box");oBox.innerHTML = "Hello & welcome, <b>'reader'</b>";//页面显示Hello & welcome, 'reader'</script>

 

  无论什么时候,只要使用innerHTML从外部插入HTML,都应该首先以可靠的方式处理HTML。IE浏览器提供了window.toStaticHTML()方法,这个方法接收一个参数,即一个HTML字符串;返回一个经过无害处理后的版本——从源HTML中删除所有脚本节点和事件处理程序属性。

var text = "<a href='#' onclick = 'alert(\"hi\");'>Click Me</a>";var sanitized = window.toStaticHTML(text);//只有IE支持console.log(sanitized);//<a href="#">Click Me</a>

 

  【限制】

    【<script>】

    大多数浏览器中,通过innerHTML插入<script>元素并不会执行其中的脚本。IE9-浏览器在满足一定条件下可以执行脚本,一是为<script>元素设置defer属性,二是<script>元素必须位于“有作用域的元素”之后。如果通过innerHTML插入的字符串开头就是一个“无作用域的元素”,那么IE会在解析这个字符串前先删除该元素。

<div id="box"></div><script>var oBox = document.getElementById("box");//innerHTML字符串一开始就是一个无作用域的元素,所以这个字符串会变成空字符串。oBox.innerHTML = "<script defer>alert('hi');<\/script>";</script>  如果想插入这段脚本,必须在前面添加一个有作用域的元素,可以是一个文本节点,也可以是一个没有结束标签的元素如<input>。以下这三种方法都可以让页面弹出"hi";<div id="box"></div><script>var oBox = document.getElementById("box");oBox.innerHTML = "&nbsp;<script defer>alert('hi');<\/script>";oBox.innerHTML = "<div>&nbsp;</div><script defer>alert('hi');<\/script>";oBox.innerHTML = "<input type='hidden'><script defer>alert('hi');<\/script>";</script>

    【<style>】

     大多数浏览器都支持以直观的方式通过innerHTML插入<script>标签

<div id="box"></div><script>var oBox = document.getElementById("box");//IE8-浏览器无变化,其他浏览器背景变成红色oBox.innerHTML = "<style type='text\/css'>body{background-color: red;}</style>";</script>      由于IE8-浏览器中,<style>是一个没有作用域的元素,所以必须设置一个前置的作用域元素<div id="box"></div><script>var oBox = document.getElementById("box");oBox.innerHTML = "_<style type='text\/css'>body{background-color: red;}</style>";oBox.removeChild(oBox.firstChild);</script>

 

outerHTML

  在读模式下outerHTML返回调用它的元素及所有子节点的HTML标签。在写模式下,outerHTML会根据指定的HTML字符串创建新的DOM子树,然后用这个DOM子树完全替换调用元素。

<ul id="list">  <li >1</li>  <li >2</li></ul><script>var oList = document.getElementById('list');/*返回<ul id="list">  <li >1</li>  <li >2</li></ul>*///IE8-浏览器会将所有标签转换成大写形式,且不包含空白文本节点console.log(oList.outerHTML);</script>

  写模式下新创建的元素将取代本身

<ul id="list">  <li >1</li>  <li >2</li></ul><script>var oList = document.getElementById('list');oList.outerHTML = "<div></div>";console.log(document.getElementById('list'));//null</script>

 

innerText

  通过innerText属性可以操作元素中包含的所有文本内容,包括子文档树中的文本。在通过innerText读取值时,它会按照由浅入深地顺序,将子文档树中的所有文本拼接起来。在通过innerText写入值时,结果会删除元素的所有子节点,插入包含相应文本值的文本节点。(firefox不支持)

<ul id="list">  <li >1</li>  <li >2</li></ul><script>var oList = document.getElementById('list');console.log(oList.innerText);//除了firefox,其他浏览器都输出1 2oList.innerText="hello & welcome <b>reader</b>";//页面上显示hello & welcome <b>reader</b></script>

 

outerText

  除了作用范围扩大到了包含调用它的节点之外,outerText与innerText基本上没有多大区别,在读取文本值时,outerText与innerText的结果完全一样,但在写模式下,outerText就完全不同了:outerText不只是替换调用它的元素的子节点,而是会替换整个元素。(firefox不支持)

<ul id="list">  <li >1</li>  <li >2</li></ul><script>var oList = document.getElementById('list');console.log(oList.outerText);//1 2 oList.outerText = "hello & welcome <b>reader</b>";//页面上显示hello & welcome <b>reader</b>console.log(document.getElementById('list'));//null</script>

 

textContent

  textContent属性与innerText属性类似。但实际上innerText与textContent返回的内容并不完全一样。innerText会忽略行内的样式和脚本,而textContent则会像返回其他文本一样,返回行内的样式和脚本。避免跨浏览器兼容的问题的最佳途径,就是从不包含行内样式或行内脚本的DOM子树副本或DOM片段中读取文本(IE8-浏览器不支持)

<ul id="list">  <li >1</li>  <li >2</li></ul><script>var oList = document.getElementById('list');console.log(oList.textContent);//除了IE8-浏览器,其他浏览器都输出1 2oList.textContent="hello & welcome <b>reader</b>";//页面上显示hello & welcome <b>reader</b></script>

 

  所以,innerText与textContent的兼容写法为:

<ul id="list">  <li >1</li>  <li >2</li></ul><script>var oList = document.getElementById('list');function getInnerText(element){  return (typeof element.textContent == "string") ? element.textContent : element.innerText;}function setInnerText(element,text){  if(typeof element.textContent == "string"){    element.textContent = text;  }else{    element.innerText = text;  }}console.log(getInnerText(oList));//1 2 setInnerText(oList,"hello & welcome <b>reader</b>")//页面上显示hello & welcome <b>reader</b></script>

 

内存与性能  

  当某个元素有一个事件处理程序,在使用某个属性将该元素从文档树中删除后,元素与事件处理程序之间的绑定关系在内存中并没有一并删除,如果这种情况频繁出现,页面占用的内在数量就会明显增加。因此,使用innerHTML、outerHTML属性时,最好先手工删除要被替换元素的所有事件处理程序和JavaScript对象属性。
最好将设置innerHTML或outerHTML的次数控制在合理的范围内。

for(var i = 0; len = values.length; i < len; i++){  //要避免这种频繁操作  ul.innerHTML += "<li>" + values[i] + "</li>";}

  这种每次循环都设置一次innerHTML的做法效率很低,而且,每次循环还要从innerHTML中读取一次信息,就意味着每次循环要访问两次innerHTML。最好的做法是单独构建字符串,然后再一次性地将字符串赋值给innerHTML。

var itemsHtml = "";for(var i = 0; len = values.length; i < len; i++){  itemsHtml += "<li>" + values[i] + "</li>";}//这种效率要高得多,因为它只对innerHTML执行了一次赋值操作。ul.innerHTML = itemsHtml;