Element.innerHTML属性:

操作元素内HTML内容,即可设置或获取利用HTML代码表示的元素的后代;

在读取时,该属性返回与调用元素的所有子节点(包括元素、注释和文本节点)对应的HTML代码字会串,如:

innerhtml失效第47节 HTML5扩大操作元素内容零点法式员王唯 Vue.js

&lt;div id=&#34;mydiv"> <h2>零点程序员</h2> <ul id="myList"> <li>HTML</li> <li class="current">CSS</li> <li>JavaScript</li> </ul></div><script>var mydiv = document.getElementById("mydiv");console.log(mydiv.innerHTML);</script>

注:不同浏览器返回的文本格式有可能不同,比如,部分低版本会把所有标签转换为大写;其余,浏览器会按照原来文档的格式返回,包括空格和缩进;

在写入时,会将给定的字符串解析为DOM子树,将用这个DOM子树更换调用元素原来的所有子节点;如果设置的值是文本没有HTML标签,其结果便是纯文本,也便是文本节点,此时,如果该文本节点包含字符&、<或>, innerHTML将这些字符分别返回为&、<和>;

mydiv.innerHTML = "零点程序员 & zeronetwork 主讲><b>\"王唯\"</b>";console.log(mydiv.innerHTML);mydiv.innerHTML = "零点程序员";

设置元素的innerHTML属性将会删除该元素的所有后代,因此,如果要保留原来的内容,可以在innerHTML属性的根本上,可以利用+=进行赋值,也就达到了追加内容的效果;

mydiv.innerHTML += "<b>大师哥王唯</b>";

如果设置innerHTML属性时,利用了不合法的HTML代码,浏览器会自动改动,但要避免涌现这种问题;

其余,不许可document工具利用该属性,如果利用了,会静默失落败;

设置了innerHTML属性后,可以像访问文档中的其他节点一样访问新创建的节点;

console.log(mydiv.childNodes);

从实质上来看,设置innerHTML属性,浏览器会把给定的值被解析为HTML或者XML,结果便是一个DocumentFragment工具,个中保存着代表元素的DOM节点,然后再append到元素中;

innerHTML也有一些限定,在多数浏览器中,通过innerHTML插入的<script> 元素不会被实行,由于有可能会产生潜在的安全问题;

var content = document.getElementById("content");content.innerHTML = "<script>alert('wangwei');<\/script>";

纵然如此,利用innerHTML属性也不能肃清潜在的风险,比如,绕过<script>标签,把脚本绑定到干系的事宜中;

mydiv.innerHTML = "<img src='nourl' onerror='alert(\"加载图片出错啦\")'>";

通过innerHTML写入<style>元素就可以运行;如:

mydiv.innerHTML = "<style>body{background-color:purple;}</style>";// 放在head中document.head.innerHTML += "<style>body{background-color:purple;}</style>";console.log(document.head.innerHTML);

在设置innerHTML属性时,虽然元素的所有子元素被更换,其仍被保存在内存中,如果事先有变量在引用这些子元素,在设置innerHTML后,这些变量仍将保持对原始子元素的引用;

var mydiv = document.getElementById("mydiv");var h2 = mydiv.querySelector("h2");mydiv.innerHTML = "新内容";console.log(h2);mydiv.appendChild(h2);

并不是所有元素都有innerHTML属性,不支持的有<col> <colgroup> <frameset> <head> <html> <style> <table> <tbody> <thead> <tfoot> <title> <tr>

无论什么时候插入外界的HTML内容时,都该当对HTML进行无害化处理,IE8供应了window.toStaticHTML()方法,接管一个HTM字符串,返回一个经由无害化处理后的版本;

var mydiv = document.getElementById("mydiv");var text = "<a href='#' onclick='alert(\"hi\")'>zeronetwork</a>";// mydiv.innerHTML = text;var sanitized = window.toStaticHTML(text); // [ˈsænɪtaɪzd]console.log(sanitized); // 非IE会抛出非常mydiv.innerHTML = sanitized;

小示例:

利用innerHTML创建一种机制用于将记录到页面中的一个元素中;

<style>.box{width: 600px;height: 300px;border:1px solid black; padding: 2em; overflow: hidden scroll;}</style><div class="box"> <h2>日志:</h2> <div class="log"></div></div><script>function log(msg){ var logEle = document.querySelector(".log"); var time = new Date().toLocaleTimeString(); logEle.innerHTML += time + ": " + msg + "<br/>"; }// log("打印一些数据");// 定义一个事宜处理程序function logEvent(event){ var msg = "Event <strong>" + event.type + "</strong> at <em>" + event.clientX + "," + event.clientY + "</em>"; log(msg);}// 绑定事宜处理程序var boxEle = document.querySelector(".box");boxEle.addEventListener("mousedown", logEvent);boxEle.addEventListener("mouseup", logEvent);boxEle.addEventListener("click", logEvent);boxEle.addEventListener("mouseenter", logEvent);boxEle.addEventListener("mouseleave", logEvent);</script>

Element.outerHTML属性:

与innerHTML属性基本同等,不同点是,innerHTML是访问和设置元素的所有子节点,而outerHTML属性不仅包括它的所有子节点,也包括它本身;

console.log(mydiv.outerHTML);mydiv.outerHTML = "<p><h2>零点网络</h2></p>";

如果元素没有父元素,即如果它是文档的根元素,在设置其outerHTML属性将抛出非常,如:

document.documentElement.outerHTML = "content"; // 非常

这个属性运用的机会非常少;

HTMLElement.innerText属性:

可以操作元素中包含的所有文本,最初是由IE实现的,后来被纳入标准中;

var mydiv = document.getElementById("mydiv");console.log(mydiv.innerText);mydiv.innerText = "零点程序员";console.log(mydiv.innerText);

输出一个文档树时,无论文本位于文档树中的什么位置,会按照由浅入深的顺序,将子文档树中的所有文本拼接起来;

<div id="content"> <p>零点网络<strong>zerontwork</strong>是一家从事IT教诲的公司</p> <ul> <li>HTML</li> <li>CSS</li> <li>Javascript</li> </ul></div><script>var content = document.getElementById("content");console.log(content.innerText);// 返回// 零点网络zerontwork是一家从事IT教诲的公司//// HTML/// CSS// Javascript</script>

由于不同浏览器处理空缺字符的办法不同,因此输出的文本可能会也可能不会包含原始的HTML代码中的缩进;

利用innerText属性设置内容时,会移除原来所有的子节点,将永久只会天生当前节点的一个子文本节点;如果设置的内容包括HTML标签,会自动被转码,也便是说,会对所有涌如今文本中的HTML语法字符进行编码(>、<、”、&);

mydiv.innerText = "<h2>wangwei</h2>"; // < > 会被转义

由于在访问innerText属性时,其会过滤掉html标签,以是可以利用它的这个特点,快速过滤掉元素的HTML标签,即把innerText设置为innerText;

content.innerText = content.innerText;console.log(content.innerText);

如果在设置innerHTML属性时,赋给的便是纯文本字符串,那它就与innerText属性浸染一样了;

var mydiv = document.getElementById("mydiv");mydiv.innerText = "零点网络 zeronetwork";mydiv.innerHTML = "零点网络 zeronetwork";mydiv.innerText = "零点网络\nzeronetwork"; // 有brmydiv.innerHTML = "零点网络\nzeronetwork"; // 无br,但源码格式有换行

由于innerHTML是解析html标签的,而\n不是标签,以是当作空格被忽略了;但在innerText中,浏览器碰着\n,就会实行换行,以是把它解析为<br>;

在实际利用中,如果要过滤html标签,可以利用正则,如:

// 去除html标签可以利用正则content.innerHTML = content.innerHTML.replace(/<.+?>/img,"");console.log(content.innerText); // 没有格式<br>console.log(content.innerHTML); // 没有格式<br>

HTMLElement.outerText属性:

与innerText一样,只不过更换的是元素(包括子节点)本身;其是一个非标准属性;

var mydiv = document.getElementById("mydiv");console.log(mydiv.innerText);console.log(mydiv.outerText); // 返回值与innerText同等

在读取文本值时,outerText和innerText的结果完备一样;

但在写模式下,outerText就完备不同了,其本身都会被新的文本节点都替代,从文档中被删除,但其仍旧被保存在内存中,如果有变量引用,还可以再利用;

mydiv.outerText = "零点程序员";console.log(mydiv); // 依然保留着原有的引用

FF不支持outerText属性,如:

mydiv.outerText = "零点程序员"; // 在FF中失落效// 在FF中返回undefined,如果有上一行,会打印出“零点程序员”,但这和内置的outerText没有关系console.log(mydiv.outerText);

在实际利用中,只会用到innerHTML和innerText,其他两个一样平常不用,也没有多大的实际意义;

Node.textContent属性:

DOM3规定了一个属性textContent,该属性被定义在Node接口中,它的浸染类似innerText属性,返回一个节点及其后代的所有文本内容;

var mydiv = document.getElementById("mydiv");console.log(mydiv.innerText);console.log(mydiv.textContent); // 返回值与innerText基本同等,但格式不一样

如果设置textContent属性,会删除该元素的所有子节点,并被更换为包含指定字符串的一个单独的文本节点;

var mydiv = document.getElementById("mydiv");mydiv.textContent = "大师哥王唯";mydiv.textContent = "<h3>大师哥王唯</h3>"; // 会被转码console.log(mydiv.textContent);console.log(mydiv.childNodes); // NodeList [text]

如果节点是文本节点,此属性可用于取代 nodeValue 属性,如;

var h2 = document.querySelector("h2").firstChild; // 取得文本节点console.log(h2.textContent); // zeronetworkconsole.log(h2.nodeValue); // zeronetworkh2.nodeValue = "零点程序员";console.log(h2.textContent); // 零点程序员console.log(h2.nodeValue); // 零点程序员

可以看出,两者是联动的;

如果事先有变量引用着它的后代节点,纵然节点利用该方法移除所有后代节点,但被引用的后代节点依然存在,可以被再次利用;

var content = document.getElementById("content");var h2 = content.querySelector("h2"); // content中的h2content.textContent = "王唯";console.log(content.textContent);console.log(h2); // <h2>zeronetwork</h2>console.log(h2.parentElement); // nullvar mydiv = document.getElementById("mydiv");mydiv.appendChild(h2);

与innerText属性的差异:

两者的返回的内容并不完备一样,比如在输出的格式上其与innerText是不同的,其会保留代码中的空缺符;同时,innerText针对表格,会试图保留表格的格式;

var mytable = document.getElementById("mytable");console.log(mytable.innerText);console.log(mytable.textContent);

textContent属性会返回元素的所有内容,包括个中的样式和脚本代码,而innerText只返回能呈现在页面上的元素;

// 在mydiv中添加<style>和<script>标签var mydiv = document.getElementById("mydiv");console.log(mydiv.innerText); // 不包括<style>和<script>// 包括<style>和<script>标签内的内容,但该标签被过滤了console.log(mydiv.textContent);

既然innerText只返回能呈现在页面上的元素,以是它的返回值会受CSS样式的影响,不会返回被CSS隐蔽的元素的文本;

<!-- textContent返回值没有变革,但innerText不包括"HTML"和"CSS" --><ul id="mylist"> <li style="visibility: hidden;">HTML</li> <li style="display: none;">CSS</li> <li>JavaScript</li></ul>

textContent属性能返回文本节点的文本内容,而innerText会返回undefined;如果是文本节点调用textContent属性,其返回值与nodeValue同等;

innerHTML有可能会引发安全问题,但textConent却不会;

mydiv.innerHTML = "<img src='nourl' onerror='alert(\"加载图片出错啦\")'>";mydiv.textContent = "<img src='nourl' onerror='alert(\"加载图片出错啦\")'>";console.log(mydiv.childNodes); // index.html:20 NodeList [text]

第一行的onerror会被实行,第二行不会实行,并且其被解析为文本节点,如此,textContent不会引发安全问题;

所有主流的浏览器都支持textContent属性,但IE8及以下不支持,可以包装一个兼容的函数:

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;}document.write(getInnerText(content));setInnerText(content, "零点程序员");

或者直接定义在Node.prototype中:

if(Object.defineProperty && Object.getOwnPropertyDescriptor && !Object.getOwnPropertyDescriptor(Node.prototype, "textContent")){ (function(){ var innerText = Object.getOwnPropertyDescriptor(HTMLElement.prototype, "innerText"); Object.defineProperty(Node.prototype, "textContent",{ get: function(){ return innerText.get.call(this); }, set: function(s){ return innerText.set.call(this, s); } }); })();}

<script>元素中的文本:

内联的<script>元素有一个text属性用来获取它们的文本;

<script> console.log("function"); function func(){return true;}</script><script>var script = document.getElementsByTagName("script")[0];console.log(script.innerText);console.log(script.textContent);console.log(script.text); // 三者输出同等</script>

如果将<script>元素的type属性设置为”text/x-custom-data”,就表明了脚本为不可实行的Javascript代码,如此,Javascript解析器将忽略该脚本,这也使得<script>元素可以被用来嵌入任意文本内容;

<script type="text/x-custom-data"> console.log("function"); function func(){return true;}</script><script>var script = document.getElementsByTagName("script")[0];console.log(script.innerText);console.log(script.textContent);console.log(script.text); // 三者输出同等</script>

<script type="text/x-custom-data"><div style="border:1px solid red; width:300px;"> <h2>视频教程</h2></div></script><script>var script = document.getElementsByTagName("script")[0];var mydiv = document.getElementById("mydiv");mydiv.innerHTML = script.text;</script>

Element.insertAdjacentHTML(position, text)方法:

该方法会将任意的HTML字符串text解析为Element元素,并将结果节点插入到DOM树中的指定的元素”相邻”的position位置;该方法最早是在IE4中涌现的;它吸收两个参数:插入位置和要插入的HTML文本;

第一个参数position的可能值:

beforebegin:在当前元素之前插入一个紧邻的同辈元素;afterbegin:在当前元素之下插入一个新的子元素或在第一个子元素之前插入新的子元素;beforeend:在当前元素之下插入一个新的子元素或在末了一个子元素之后插入新的子元素;afterend:在当前元素之后插入一个紧邻的同辈元素;

第二个参数text为HTML字符串,如果浏览器无法解析,会抛出错误,如;

var mydiv = document.getElementById("mydiv");mydiv.insertAdjacentHTML("beforebegin","<p>前一个同辈元素</p>");mydiv.insertAdjacentHTML("afterbegin","<p>作为第一个子元素</p>");mydiv.insertAdjacentHTML("beforeend","<p>末了一个子元素</p>");mydiv.insertAdjacentHTML("afterend","<p>后一个同辈元素</p>");

insertAdjacentHTML()方法同innerHTML属性一样,会碰着安全问题,在利用该属性插入HTML内容时,须要转义之后才能利用;

其余,如果元素没有子元素的时候,其和innerHTML就非常相像了;

var newdiv = document.createElement("div");newdiv.insertAdjacentHTML("afterbegin", "<p>零点程序员</p>");// 同以下newdiv.innerHTML = "<p>零点程序员</p>";document.body.appendChild(newdiv);

须要把稳的是,如果position为beforebegin或afterend,那该元素必须具有一个parent元素;

var newdiv = document.createElement("div");// 非常:The element has no parent,此时newdiv并没有被添加到DOM树中,它并没有父节点,但是如果把下面行互换一下,就可以了;newdiv.insertAdjacentHTML("afterend", "<p>零点程序员</p>");document.body.appendChild(newdiv);

基于insertAdjacentHTML()方法定义一个更符合语义逻辑的一个工具,如:

// Insert.before()、Insert.after()、Insert.atStart()和Insert.atEnd()var Insert = { before: function(e,h) { if(e.parentElement) e.insertAdjacentHTML("beforebegin", h); }, after: function(e,h) { if(e.parentElement) e.insertAdjacentHTML("afterend", h); }, atStart: function(e,h) {e.insertAdjacentHTML("afterbegin", h);}, atEnd: function(e,h) {e.insertAdjacentHTML("beforeend", h);}};var mydiv = document.getElementById("mydiv");Insert.before(mydiv, "<h2>zeronetwork</h2>");// 或者// 假定where值为before、after、innerfirst和innerlastfunction insertHTML(el, where, html){ if(!el) return false; var _where = "beforeend"; switch(where){ case "before": _where = "beforebegin"; break; case "after": _where = "afterend"; break; case "innerfirst": _where = "afterbegin"; break; case "innerlast": _where = "beforeend"; break; default: _where = "beforeend"; break; } if(_where == "beforebegin" || _where == "afterend"){ if(!el.parentElement) return false; } el.insertAdjacentHTML(_where, html);}var mydiv = document.getElementById("mydiv");insertHTML(mydiv, "innerfirst", "<h2>zeronetwork</h2>");

小示例,添加商品:

<div class="container"> <div class="formdiv"> <label>商品:</label><input type="text" id="product" /><br/> <label>价格:</label><input type="text" id="price" /><br/> <label>数量:</label><input type="text" id="quantity" /><br/> <button id="btnAdd">添加</button> </div> <table class="table"> <thead> <tr> <th>序号</th><th>商品</th><th>价格</th><th>数量</th><th>金额</th> </tr> </thead> <tbody id="data"></tbody> </table></div><script>var id=1;var btnAdd = document.getElementById("btnAdd");btnAdd.addEventListener("click",function(e){ var content = document.getElementById("data"); var product = document.getElementById("product").value; var price = document.getElementById("price").value; var quantity = document.getElementById("quantity").value; var total = price quantity; var newEntry = "<tr>" + "<td>" + id + "</td>" + "<td>" + product + "</td>" + "<td>" + price + "</td>" + "<td>" + quantity + "</td>" + "<td>" + total + "</td>" + "</tr>"; content.insertAdjacentHTML('afterbegin', newEntry); id++;},false);</script>

Element.insertAdjacentText(position, text)方法:

该方法与insertAdjacentHTML()类似,只不过插入的是纯文本内容,它的浸染是将一个给定的文本text插入到相对付被调用的元素的给定position位置;

position的值insertAdjacentHTML()中的position是一样的;

var mydiv = document.getElementById("mydiv");mydiv.insertAdjacentText("afterbegin","王唯");mydiv.insertAdjacentText("afterend","zeronetwork");

如果text是html字符串,也会被当作纯文本进行处理,如:

// 页面输出:<h2>王唯</h2>mydiv.insertAdjacentText("afterbegin","<h2>王唯</h2>");

Element. insertAdjacentElement(position, element)方法:

将一个给定的元素节点插入到相对付被调用的元素的给定的position位置;与insertAdjacentHTML()方法类似,只不过插入的是一个节点工具;该方法会返回一个Element工具;

var mydiv = document.getElementById("mydiv");var div = document.createElement("div");div.innerHTML = "<h2>zeronetwork</h2>";div.style.width = "200px";div.style.height = "100px";div.style.backgroundColor = "lightgray";var newdiv = mydiv.insertAdjacentElement("beforeend", div);console.log(div === newdiv); // true

github上有人分享了一个包装的方法,便是利用以上原生的方法;

// 把一个节点插入到DOM树中的一个位置function dominsert(parent, child, position){ var pos = position || 'beforeend'; if(typeof child === 'string') dominsert.html(parent, child, pos); else dominsert.element(parent, child, pos);}// 利用原生的insertAdjacentHTML()方法dominsert.html = function(parent, child, position){ parent.insertAdjacentHTML(position, child);};// 利用原生的insertAdjacentElement()或insertBefore()方法dominsert.element = function(parent, child, position){ if(parent.insertAdjacentElement) parent.insertAdjacentElement(position, child); else{ switch (position){ case "beforebegin": parent.parentNode.insertBefore(child, parent); break; case "afterbegin": parent.insertBefore(child, parent.firstChild); break; case "beforeend": parent.appendChild(child); break; case "afterend": parent.parentNode.insertBefore(child, parent.nextSibling); break; } }};var mydiv = document.getElementById("mydiv");dominsert(mydiv,"<span>web前端</span>");dominsert(mydiv, "<b>零点程序员</b>", 'beforebegin');console.log(mydiv);

内存和性能问题:

利用以上的方法更换子节点可能会导致浏览器的内存占用问题,尤其是在IE中,问题更加明显;

如果被删除的子树中的元素设置了事宜处理程序或者引用了一个Javascript工具作为属性,被删除的元素与事宜处理程序或引用的JS工具之间的绑定关系在内存中并没有一并删除;如果这种情形频繁涌现,页面占用的内存数量就会明显增加;因此,在利用innerHTML、outerHTML属性和insertAdjacentHTML()方法时,最妙手工先移除要被更换的元素的所有事宜处理程序和JS工具属性;

不要反复地利用innerHTML插入HTML;

var arr = ["HTML","CSS","JavaScript"];var ul = document.getElementById("myList");for(var i=0,len=arr.length; i < len; i++){ ul.innerHTML += "<li>" + arr[i] + "</li>"; }

,最好的做法是:单独构建字符串变量,再一次性的把结果赋给innerHTML;

console.time("insert");var lisHTML = "";for(var i=0,len=arr.length; i<len;i++){ lisHTML += "<li>" + arr[i] + "</li>";}ul.innerHTML = lisHTML;console.timeEnd("insert");

adjacent三个方法与insertBefore()、appendChild()和innerHTML的比较;

在某些时候,这些方法属性都可以达到同样的目的,但在实际开拓中,要针对当时的情形,选择一个得当的方法,没有哪个方法就一定比其余的方法更好,只有相对的得当;

同时,这三个方法的性能虽然不一样,但相差不大,险些可以忽略;

insertAdjacentHTML()与innerHTML属性的性能:

insertAdjacentHTML()方法不会重新解析它正在利用的元素,因此它不会毁坏元素内的现有元素,这就避免了额外的序列化步骤,但利用innerHTML时,特殊是在原有的根本上追加元素时,都会对原有的元素重新序列化,因此,前者比后者效率更快;

appendChild()与insertAdjacentHTML()方法的性能;

// time 10msconsole.time("append");for(var i=0; i<1000; i++) mydiv.appendChild(document.createElement("div"));console.timeEnd("append");// tim 30msconsole.time("adjacent");for(var i=0; i<1000; i++) mydiv.insertAdjacentHTML("beforeend","<div></div>");console.timeEnd("adjacent");

可以看到appendChild()方法比insertAdjacentHTML()方法快很多,但是改进以上代码后,为其添加有文本内容的元素,如;

// time 30ms多console.time("append");for(var i=0; i<1000; i++){ var div = document.createElement("div"); var h2 = document.createElement("h2"); h2.appendChild(document.createTextNode("零点程序员")); div.appendChild(h2); var p = document.createElement("p"); p.appendChild(document.createTextNode("由大师哥王唯主讲")); div.appendChild(p); mydiv.appendChild(div);}console.timeEnd("append");// time 40ms多console.time("adjacent");for(var i=0; i<1000; i++) mydiv.insertAdjacentHTML("beforeend","<div><h2>零点程序员</h2><p>由大师哥王唯主讲</p></div>");console.timeEnd("adjacent");

可以看到,两者相差10ms,险些可以忽略不计;

比较appendChild()与insertAdjacentElement方法的性能;

如:把测试appendChild()方法中的mydiv.appendChild(div)改成mydiv.insertAdjacentElement("beforeend", div);即可;

创造两者险些相同;

比较insertBefore()与以上两者的性能;

如:把测试appendChild()方法中的mydiv.appendChild(div),改成mydiv.insertBefore(div, mydiv.lastChild);,结束也大同小异;

小实例,排序表格;

基于表格指定列中单元格的值来进行排序;

<table id="mytable" border="1"> <thead> <tr> <th>ID</th><th>Name</th><th>Sex</th> </tr> </thead> <tbody> <tr> <td>1</td><td>wangwei</td><td>女</td> </tr> <tr> <td>2</td><td>jingjing</td><td>男</td> </tr> <tr> <td>3</td><td>juanjuan</td><td>女</td> </tr></tbody></table><script>// 根据指定表格每行第n个单元格的值,对第一个<tbody>中的行进行排序// 如果存在comparator函数则利用它,否则按字母表顺序比较function sortrows(table, n, comparator){ var tbody = table.tBodies[0]; // 第一个<tbody>,可能是隐式创建的 var rows = tbody.getElementsByTagName("tr"); // tbody中所有行 rows = Array.prototype.slice.call(rows, 0); // 变成数组 // 基于第n个<td>元素的值进行排序 rows.sort(function(row1, row2){ var cell1 = row1.getElementsByTagName("td")[n]; // 得到第n个单元格 var cell2 = row2.getElementsByTagName("td")[n]; // 同上 var val1 = cell1.textContent || cell1.innerText; // 得到文本内容 var val2 = cell2.textContent || cell2.innerText; if(comparator) return comparator(val1,val2); // 进行排序 if(val1 < val2) return -1; else if(val1 > val2) return 1; else return 0; }); // rows中已经排好序,在tbody中按它们的顺序把行添加到末了 // 这将自动把它们从当前位置移走,并不是删除,而是移动 for(var i=0; i<rows.length; i++){ tbody.appendChild(rows[i]); }}// 查找元素的<th>元素,让它们可单击,可以按该列排序function makeSortable(table){ var headers = table.getElementsByTagName("th"); for(var i=0; i<headers.length; i++){ (function(n){ headers[i].onclick = function() { sortrows(table, n); }; }(i)); }}var mytable = document.getElementById("mytable");makeSortable(mytable);</script>

小实例,天生目录表:

<style>#TOC{border:solid black 1px; margin:10px; padding: 10px;}.TOCEntry{}.TOCEntry a{text-decoration: none;}.TOCLevel1{font-size: 2em;}.TOCLevel2{font-size: 1.5em; margin-left: 1em;}.TOCSectNum::after{content: ": ";}</style><script>// 当实行这个函数时会去文档中查找id为"TOC"的元素;// 如果这个元素不存在,就创建一个元素// 天生的TOC目录应该具有自己的CSS样式,全体目录区域的样式className设置为"TOCEntry";// 为不同层级的目录标题定义不同的样式,<h1>标签天生的标题className为"TOCLevel1",// <h2>标签天生的标题className为”TOCLevel2“,以此类推;段编号的样式为"TOCSectNum"function createToc(){ // 查找TOC容器元素,如果不存在,则在文档开头处创建一个 var toc = document.getElementById("TOC"); if(!toc){ toc = document.createElement("div"); toc.id = "TOC"; document.body.insertBefore(toc, document.body.firstChild); } // 查找所有的标题元素 var headings; if(document.querySelectorAll) headings = document.querySelectorAll("h1,h2,h3,h4,h5,h6"); else headings = findHeadings(document.body, []); // 递归遍历document的body,查找标题元素 function findHeadings(orrt, sects){ for(var c = root.firstChild; c!=null; c=c.nextSibling){ if(c.nodeType !== 1) continue; if(c.tagName.length == 2 && c.tagName.charAt(0) == "H") sects.push(c); else findHeadings(c, sects); } return sects; } // 初始化一个数组来保存跟踪章节号 var sectionNumbers = [0,0,0,0,0,0]; // 循环找到所有标题元素 for(var h=0; h<headings.length; h++){ var heading = headings[h]; // 跳过在TOC容器中的标题元素 if(heading.parentNode == toc) continue; // 获取标题的级别 var level = parseInt(heading.tagName.charAt(1)); if(isNaN(level) || level < 1 || level > 6) continue; // 对付该标题级别增加sectionNumbers对应的数字 // 并重置所有标题比它级别低的数字为零 sectionNumbers[level-1]++; for(var i=level; i<6; i++) sectionNumbers[i] = 0; // 将所有标题级的章节号组合产生一个章节号,如2.3.1 var sectionNumber = sectionNumbers.slice(0, level).join("."); // 为标题级别增加章节号 // 把数字放在<span>中,使得其可以秀样式润色 var span = document.createElement("span"); span.className = "TOCSectNum"; span.innerHTML = sectionNumber; heading.insertBefore(span, heading.firstChild); // 用命名的锚点将标题包起来,以便为它增加链接 var anchor = document.createElement("a"); anchor.name = "TOC" + sectionNumber; heading.parentNode.insertBefore(anchor, heading); anchor.appendChild(heading); // 为该节创建一个链接 var link = document.createElement("a"); link.href = "#TOC" + sectionNumber; // 链接目标地址 link.innerHTML = heading.innerHTML; // 链接文本与实际标题同等 // 将链接放在一个div中,div用基于级别名字的样式润色 var entry = document.createElement("div"); entry.className = "TOCEntry TOCLevel" + level; entry.appendChild(link); // 该div添加到TOC容器中 toc.appendChild(entry); }};window.onload = function(){createToc();}</script>

Web前端开拓之Javascript