DOM中文本和标记的插入

innerHTML

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

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

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

  

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

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

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

<div class="box" 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 class="box" id="box"></div>
<script>
var oBox = document.getElementById("box");
//innerHTML字符串一开始就是一个无作用域的元素,所以这个字符串会变成空字符串。
oBox.innerHTML = "<script defer>alert('hi');<\/script>";
</script>
    如果想插入这段脚本,必须在前面添加一个有作用域的元素,可以是一个文本节点,也可以是一个没有结束标签的元素如<input>。以下这三种方法都可以让页面弹出"hi";
<div class="box" 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 class="box" 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 class="box" 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 class="list" id="list">
    <li class="in">1</li>
    <li class="in">2</li>
</ul>
<script>
var oList = document.getElementById('list');
/*返回
<ul class="list" id="list">
    <li class="in">1</li>
    <li class="in">2</li>
</ul>*/
//IE8-浏览器会将所有标签转换成大写形式,且不包含空白文本节点
console.log(oList.outerHTML);
</script>
复制代码

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

复制代码
<ul class="list" id="list">
    <li class="in">1</li>
    <li class="in">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 class="list" id="list">
    <li class="in">1</li>
    <li class="in">2</li>
</ul>
<script>
var oList = document.getElementById('list');
console.log(oList.innerText);//除了firefox,其他浏览器都输出1 2
oList.innerText="hello & welcome <b>reader</b>";//页面上显示hello & welcome <b>reader</b>
</script>
复制代码

 

outerText

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

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

 

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

复制代码
<ul class="list" id="list">
    <li class="in">1</li>
    <li class="in">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;
复制代码

 

好的代码像粥一样,都是用时间熬出来的
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值