幾年來,HTML5移動開發技術如此火爆,學習HTML5開發技術的人員也是越來越多。那么我們在培訓學習HTML5技術時,應該了解哪些呢?今天華清遠見HTML5培訓專家就來為大家指點迷津。
首先,明確HTML5是什么?
HTML5是HTML經過第五次重大修改,用于取代1999年所制定的HTML4.01和XHTML1.0標準的HTML標準版本。HTML5的具體定義為:“萬維網的核心語言,標準通用標記語言下的一個應用超文本標記語言的第五次重大修改。”
其次,明確HTML5技術特點
NO1.語義特性
HTML5賦予網頁更好的意義和結構,更加豐富的標簽將隨著對RDFa的,微數據與微格式等方面的支持,構建對程序、對用戶都更有價值的數據驅動的Web。
NO2.本地存儲特性
基于HTML5開發的網頁app擁有更短的啟動時間,更快的聯網速度,這些全得益于HTML5 app Cache,以及本地存儲功能。
NO3.設備兼容特性
從Geolocation功能的API文檔公開以來,HTML5為網頁應用開發者們提供了更多功能上的優化選擇,帶來了更多體驗功能的優勢。HTML5提供了前所未有的數據與應用接入開放接口。使外部應用可以直接與瀏覽器內部的數據直接相連,例如視頻影音可直接與microphones及攝像頭相聯。
NO4.連接特性
更有效的連接工作效率,使得基于頁面的實時聊天,更快速的網頁游戲體驗,更優化的在線交流得到了實現。HTML5擁有更有效的服務器推送技術,Server-SentEvent和WebSockets就是其中的兩個特性,這兩個特性能夠幫助我們實現服務器將數據“推送”到客戶端的功能。
NO5.網頁多媒體特性
支持網頁端的Audio、Video等多媒體功能,與網站自帶的APPS,攝像頭,影音功能相得益彰。
NO6.三維、圖形及特效特性
基于SVG、Canvas、WebGL及CSS3的3D功能,用戶會驚嘆于在瀏覽器中,所呈現的驚人視覺效果。
NO7.性能與集成特性
沒有用戶會永遠等待你的Loading——HTML5會通過XMLHttpRequest2等技術,幫助您的Web應用和網站在多樣化的環境中更快速的工作。
NO8.CSS3特性
在不犧牲性能和語義結構的前提下,CSS3中提供了更多的風格和更強的效果。此外,較之以前的Web排版,Web的開放字體格式(WOFF)也提供了更高的靈活性和控制性。
HTML5技術毋庸置疑未來將成為web前端的主流開發技術,所以我們一定要抓住時代發展的機遇,如果對這方面感興趣趕緊學起來!!!
如果大家想要更加詳細的了解HTML5可以看下華清遠見的官網 http://html5.3g-edu.org/?ahbtt
JAX即“Asynchronous JavaScript and XML”(非同步的JavaScript與XML技術),指的是一套綜合了多項技術的瀏覽器端網頁開發技術。Ajax的概念由杰西·詹姆士·賈瑞特所提出。
傳統的Web應用允許用戶端填寫表單(form),當送出表單時就向網頁伺服器發送一個請求。伺服器接收并處理傳來的表單,然后送回一個新的網頁,但這個做法浪費了許多帶寬,因為在前后兩個頁面中的大部分HTML碼往往是相同的。由于每次應用的溝通都需要向伺服器發送請求,應用的回應時間依賴于伺服器的回應時間。這導致了用戶界面的回應比本機應用慢得多。
與此不同,AJAX應用可以僅向伺服器發送并取回必須的數據,并在客戶端采用JavaScript處理來自伺服器的回應。因為在伺服器和瀏覽器之間交換的數據大量減少,伺服器回應更快了。同時,很多的處理工作可以在發出請求的客戶端機器上完成,因此Web伺服器的負荷也減少了。
類似于DHTML或LAMP,AJAX不是指一種單一的技術,而是有機地利用了一系列相關的技術。雖然其名稱包含XML,但實際上數據格式可以由JSON代替,進一步減少數據量,形成所謂的AJAJ。而客戶端與服務器也并不需要異步。一些基于AJAX的“派生/合成”式(derivative/composite)的技術也正在出現,如AFLAX。
20世紀90年代,幾乎所有的網站都由HTML頁面實現,服務器處理每一個用戶請求都需要重新加載網頁。這樣的處理方式效率不高。用戶的體驗是所有頁面都會消失,再重新載入,即使只是一部分頁面元素改變也要重新載入整個頁面,不僅要刷新改變的部分,連沒有變化的部分也要刷新。這會加重服務器的負擔。
這可以用異步加載來解決。1995年,JAVA語言的第一版發布,隨之發布的的Java applets(JAVA小程序)首次實現了異步加載。瀏覽器通過運行嵌入網頁中的Java applets與服務器交換數據,不必刷新網頁。1996年,Internet Explorer將iframe元素加入到HTML,支持局部刷新網頁。
1998年前后,Outlook Web Access小組寫成了允許客戶端腳本發送HTTP請求(XMLHTTP)的第一個組件。該組件原屬于微軟Exchange Server,并且迅速地成為了Internet Explorer 4.0[2]的一部分。部分觀察家認為,Outlook Web Access是第一個應用了Ajax技術的成功的商業應用程序,并成為包括Oddpost的網絡郵件產品在內的許多產品的領頭羊。但是,2005年初,許多事件使得Ajax被大眾所接受。Google在它著名的交互應用程序中使用了異步通訊,如Google討論組、Google地圖、Google搜索建議、Gmail等。Ajax這個詞由《Ajax: A New Approach to Web Applications》一文所創,該文的迅速流傳提高了人們使用該項技術的意識。另外,對Mozilla/Gecko的支持使得該技術走向成熟,變得更為簡單易用。
使用Ajax的最大優點,就是能在不更新整個頁面的前提下維護數據。這使得Web應用程序更為迅捷地回應用戶動作,并避免了在網絡上發送那些沒有改變的信息。
Ajax不需要任何瀏覽器插件,但需要用戶允許JavaScript在瀏覽器上執行。就像DHTML應用程序那樣,Ajax應用程序必須在眾多不同的瀏覽器和平臺上經過嚴格的測試。隨著Ajax的成熟,一些簡化Ajax使用方法的程序庫也相繼問世。同樣,也出現了另一種輔助程序設計的技術,為那些不支持JavaScript的用戶提供替代功能。
對應用Ajax最主要的批評就是,它可能破壞瀏覽器的后退與加入收藏書簽功能。
在動態更新頁面的情況下,用戶無法回到前一個頁面狀態,這是因為瀏覽器僅能記下歷史記錄中的靜態頁面。一個被完整讀入的頁面與一個已經被動態修改過的頁面之間的可能差別非常微妙;用戶通常都希望單擊后退按鈕,就能夠取消他們的前一次操作,但是在Ajax應用程序中,卻無法這樣做。不過開發者已想出了種種辦法來解決這個問題,HTML5 之前的方法大多是在用戶單擊后退按鈕訪問歷史記錄時,通過建立或使用一個隱藏的IFRAME來重現頁面上的變更。(例如,當用戶在Google Maps中單擊后退時,它在一個隱藏的IFRAME中進行搜索,然后將搜索結果反映到Ajax元素上,以便將應用程序狀態恢復到當時的狀態)。
關于無法將狀態加入收藏或書簽的問題,HTML5之前的一種方式是使用URL片斷標識符(通常被稱為錨點,即URL中#后面的部分)來保持追蹤,允許用戶回到指定的某個應用程序狀態。(許多瀏覽器允許JavaScript動態更新錨點,這使得Ajax應用程序能夠在更新顯示內容的同時更新錨點。)HTML5 以后可以直接操作瀏覽歷史,并以字串形式儲存網頁狀態,將網頁加入網頁收藏夾或書簽時狀態會被隱形地保留。上述兩個方法也可以同時解決無法后退的問題。
進行Ajax開發時,網絡延遲——即用戶發出請求到服務器發出響應之間的間隔——需要慎重考慮。如果不給予用戶明確的回應[4],沒有恰當的預讀數據[5],或者對XMLHttpRequest的不恰當處理[6],都會使用戶感到厭煩[7]。通常的解決方案是,使用一個可視化的組件來告訴用戶系統正在進行后臺操作并且正在讀取數據和內容。
對程序員而言,開發Ajax應用最頭痛的問題莫過于以下幾點:
Ajax在本質上是一個瀏覽器端的技術,首先面臨無可避免的第一個問題即是瀏覽器的兼容性問題。各家瀏覽器對JavaScript/DOM/CSS的支持總有部分不太相同或是有Bug,甚至同一瀏覽器的各個版本間對于JavaScript/DOM/CSS的支持也有可能部分不一樣。這導致程序員在寫Ajax應用時花大部分的時間在調試瀏覽器的兼容性而非在應用程序本身。因此,目前大部分的Ajax鏈接庫或開發框架大多以js鏈接庫的形式存在,以定義更高階的JavaScript API、JavaScript對象(模板)、或者JavaScript Widgets來解決此問題。如prototype.js。
Ajax技術之主要目的在于局部交換客戶端及服務器之間的數據。如同傳統之主從架構,無可避免的會有部分的業務邏輯會實現在客戶端,或部分在客戶端,部分在服務器。由于業務邏輯可能分散在客戶端及服務器,且以不同之程序語言實現,這導致Ajax應用程序極難維護。如有使用者接口或業務邏輯之更動需求,再加上前一個JavaScript/DOM/CSS之兼容性問題,Ajax應用往往變成程序員的夢魘。針對業務邏輯分散的問題,Ajax開發框架大致可分為兩類:
將業務邏輯及表現層放在瀏覽器,數據層放在服務器:因為所有的程序以JavaScript執行在客戶端,只有需要數據時才向服務器要求服務,此法又稱為胖客戶端(fat client)架構。服務器在此架構下通常僅用于提供及儲存數據。此法的好處在于程序員可以充分利用JavaScript搭配業務邏輯來做出特殊的使用者接口,以符合終端使用者的要求。但是問題也不少,主因在第一,JavaScript語言本身之能力可能不足以處理復雜的業務邏輯。第二,JavaScript的執行效能一向不好。第三,JavaScript存取服務器數據,仍需適當的服務器端程序之配合。第四,瀏覽器兼容性的問題又出現。有些Ajax開發框架如DWR企圖以自動生成JavaScript之方式來避免兼容的問題,并開立通道使得JavaScript可以直接叫用服務器端的Java程序來簡化數據的存取。但是前述第一及第二兩個問題仍然存在,程序員必須費相當的力氣才能達到應用程序之規格要求,或可能根本無法達到要求。
將表現層、業務邏輯、及數據層放在服務器,瀏覽器僅有使用者接口引擎(User Interface engine);此法又稱為瘦客戶端(thin client)架構,或中心服務器(server-centric)架構。瀏覽器的使用者接口引擎僅用于反映服務器的表現層以及傳達使用者的輸入回到服務器的表現層。由瀏覽器所觸發之事件亦送回服務器處理,根據業務邏輯來更新表現層,然后反映回瀏覽器。因為所有應用程序完全在服務器執行,數據及表現層皆可直接存取,程序員只需使用服務器端相對較成熟之程序語言(如Java語言)即可,不需再學習JavaScript/DOM/CSS,在開發應用程序時相對容易。缺點在于使用者接口引擎以及表現層通常以標準組件的形式存在,如需要特殊組件(使用者接口)時,往往須待原框架之開發者提供,緩不濟急。如開源碼Ajax開發框架ZK目前支持XUL及XHTML組件,尚無XAML之支持。
JavaScript編程的最大問題來自不同的瀏覽器對各種技術和標準的支持。
XmlHttpRequest對象在不同瀏覽器中不同的創建方法,以下是跨瀏覽器的通用方法:
參考鏈接:
https://zh.wikipedia.org/zh-hans/AJAX
內容是《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
*請認真填寫需求信息,我們會在24小時內與您取得聯系。