内容是《Web前端开发之Javascript视频》的课件,请配合大师哥《Javascript》视频课程学习。
Element.innerHTML属性:
操作元素内HTML内容,即可设置或获取使用HTML代码表示的元素的后代;
在读取时,该属性返回与调用元素的所有子节点(包括元素、注释和文本节点)对应的HTML代码字会串,如:
<div id="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"; // 有br
mydiv.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); // zeronetwork
console.log(h2.nodeValue); // zeronetwork
h2.nodeValue = "零点程序员";
console.log(h2.textContent); // 零点程序员
console.log(h2.nodeValue); // 零点程序员
可以看出,两者是联动的;
如果事先有变量引用着它的后代节点,即使节点使用该方法移除所有后代节点,但被引用的后代节点依然存在,可以被再次利用;
var content = document.getElementById("content");
var h2 = content.querySelector("h2"); // content中的h2
content.textContent = "王唯";
console.log(content.textContent);
console.log(h2); // <h2>zeronetwork</h2>
console.log(h2.parentElement); // null
var 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的可能值:
第二个参数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和innerlast
function 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 10ms
console.time("append");
for(var i=0; i<1000; i++)
mydiv.appendChild(document.createElement("div"));
console.timeEnd("append");
// tim 30ms
console.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
源:升学就业帮讲师——肖云锐
1. 概述
缩写是Emmet工具箱的核心:这些特殊表达式在运行时进行解析,并转换为结构化代码块,例如HTML。该缩写的语法看起来像CSS选择器,带有一些特定于代码生成的扩展名。因此,每个Web开发人员都已经知道如何使用它。
这是一个例子:这个缩写
可以转化为:
只需一个按键。在许多编辑器(例如Eclipse,Sublime Text 2,Espresso等)中,插件还会生成适当的标签结束标记,因此您可以使用Tab键快速在生成的代码的重要位置之间移动。
缩写针对(但不限于)HTML和XML生成进行了优化,并使编写繁琐的标记代码变得轻而易举。
2. 语法
2.1 缩写语法
Emmet使用类似于CSS选择器的语法来描述元素在生成的树中的位置和元素的属性。
2.2 元素
您可以使用元素的名字,如div或p以生成 HTML标签。Emmet没有一组预定义的可用标签名称,您可以编写任何单词并将其转换为标签:div→ <div></div>,foo→ <foo></foo>等。
2.3 嵌套运算符
嵌套运算符用于将缩写元素放置在生成的树内:是将其放置在上下文元素内部或者附近。
子元素: >
你可以使用 > 运算符来实现在每一个元素中嵌套内置元素
输出:
TML编辑器是一种用于创建、编辑和预览HTML(超文本标记语言)代码的工具或应用程序。它提供了一个直观的界面,使用户能够轻松地编写和设计网页内容。本文主要介绍HTML 常用编辑器(Visual Studio Code、Sublime Text、Atom、Notepad++和Dreamweaver)。
参考文档:https://www.cjavapy.com/article/3299/
Visual Studio Code(简称VS Code)是一款由微软开发的跨平台源代码编辑器,支持Windows、macOS和Linux等多种操作系统。它被广泛用于Web开发,包括编辑HTML、CSS、JavaScript等前端技术。VS Code是一款轻量级的代码编辑器,启动迅速,占用资源少。VS Code提供了丰富的扩展和插件,可以根据需求安装插件来增强编辑器功能。
1)安装和配置
官网地址:Visual Studio Code - Code Editing. Redefined
根据操作系统下载并安装相应版本的VS Code。打开VS Code后,可以根据自己的喜好配置编辑器设置,如主题、字体等。
2)新建HTML文件
在 VS Code 安装完成后,选择" 文件(F)->新建文件(N) ",在新建的文件中输入以下代码:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>编程之路(cjavapy.com)</title>
</head>
<body>
<h1>我的第一个标题</h1>
<p>我的第一个段落。</p>
</body>
</html>
3)编辑HTML文件
在VS Code中,点击左上角的"文件"菜单,选择"打开文件",或者使用快捷键Ctrl+O(Windows)或Cmd+O(macOS)来打开HTML文件。
在编辑器中可以直接修改HTML文件的内容。VS Code会自动识别HTML标记,并提供代码高亮和智能提示功能。编辑完成后,使用快捷键Ctrl+S(Windows)或Cmd+S(macOS)来保存HTML文件。
4)插件推荐
HTML CSS Support:提供对HTML和CSS的支持,包括代码片段、自动补全等功能。
Live Server:启动一个本地开发服务器,实时预览HTML页面的效果。
Prettier:格式化HTML代码,使代码结构更整洁。
Auto Close Tag:自动闭合HTML标签,提高编码效率。
Bracket Pair Colorizer:对成对的括号进行着色,方便识别代码块。
Sublime Text是一款流行的跨平台源代码编辑器,支持Windows、macOS和Linux等多种操作系统。它被广泛用于Web开发,包括编辑HTML、CSS、JavaScript等前端技术。
Sublime Text的界面非常简洁,没有多余的菜单和工具栏,更便于专注于代码编辑。Sublime Text支持多种编程语言,包括HTML、CSS、JavaScript、Python、Java等。Sublime Text拥有强大的插件系统,用户可以根据需要安装插件来扩展编辑器功能。用户可以自定义快捷键、主题、颜色方案等,以满足个性化需求。Sublime Text启动迅速,响应快速,适合于快速编辑代码。
1)安装和配置
官网地址:Sublime Text - Text Editing, Done Right
根据操作系统下载并安装相应版本的Sublime Text。打开Sublime Text后,可以根据自己的喜好进行编辑器设置,如字体、主题等。
2)新建HTML文件
在Sublime Text 安装完成后,选择" File->New File ",在新建的文件中输入以下代码:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>编程之路(cjavapy.com)</title>
</head>
<body>
<h1>我的第一个标题</h1>
<p>我的第一个段落。</p>
</body>
</html>
3)编辑HTML文件
在Sublime Text中,点击左上角的"File"菜单,选择"Open File",或者使用快捷键Ctrl+O(Windows)或Cmd+O(macOS)来打开HTML文件。在编辑器中可以直接修改HTML文件的内容。Sublime Text会自动识别HTML标记,并提供代码高亮和智能提示功能。编辑完成后,使用快捷键Ctrl+S(Windows)或Cmd+S(macOS)来保存HTML文件。
4)插件推荐
Emmet:提供HTML/CSS快速编写和自动完成功能,可以大大提高编码效率。
Sublime Linter:对代码进行实时语法检查,帮助发现潜在的错误和警告。
Color Highlighter:对CSS中的颜色进行高亮显示,方便调试和修改样式。
SideBarEnhancements:增强侧边栏功能,提供更多文件操作选项。
Dreamweaver是由Adobe公司开发的一款全球知名的网页设计和开发工具。它为开发人员和设计师提供了一个可视化的界面,可以直观地创建和编辑网页内容,同时也支持手动编辑代码。Dreamweaver提供可视化界面,可以直观地拖拽和编辑网页元素,无需手动编写代码。除了可视化界面,Dreamweaver也支持手动编辑代码,适合于开发人员和设计师。Dreamweaver可在Windows和macOS等多个平台上运行。Dreamweaver集成了代码编辑器、预览窗口、文件管理器等功能,提供全面的开发环境。
1)安装和配置
官网地址:Website design software | Adobe Dreamweaver
根据操作系统下载并安装相应版本的Dreamweaver。打开Dreamweaver后,,根据需要进行编辑器设置,如界面语言、字体、代码颜色等。
2)编辑HTML文件
在Dreamweaver中,点击左上角的"File"菜单,选择"New",然后选择"HTML",即可新建一个空白的HTML文件。内容如下:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>编程之路(cjavapy.com)</title>
</head>
<body>
<h1>我的第一个标题</h1>
<p>我的第一个段落。</p>
</body>
</html>
使用可视化界面,可以直接拖拽页面元素、调整布局、插入图片等。若需要手动编辑HTML代码,可以在下方的代码编辑器中进行修改。Dreamweaver会自动提供代码补全和语法高亮功能。在Dreamweaver中,可以实时预览网页效果,点击右上角的"Live View"按钮即可。
3)CSS和JavaScript支持
Dreamweaver也支持CSS和JavaScript的编辑和预览,可以帮助创建更丰富的网页效果。在编辑器中可以直接编辑CSS样式和JavaScript代码,并实时查看效果。
4)网页上传和发布
Dreamweaver集成了FTP功能,可以直接将编辑好的网页上传到服务器。点击"Site"菜单,选择"Manage Sites",配置好站点设置,即可进行上传和发布。
5)Dreamweaver模板和库
Dreamweaver提供模板和库功能,可以保存和复用常用的网页元素和样式,提高开发效率。
参考文档:https://www.cjavapy.com/article/3299/
*请认真填写需求信息,我们会在24小时内与您取得联系。