目錄javascript
動態腳本css
使用<script>元素能夠向頁面中插入JavaScript代碼的兩種方式:經過src特性包含外部文件;使用這個元素自己來包含代碼
動態腳本指的是頁面加載時不存在,在未來某一刻須要經過修改DOM動態添加腳本。跟操做HTML元素同樣,建立動態腳本也有兩種方式:插入外部文件和直接插入JS代碼。
(1)插入外部文件java
//動態建立<script type="text/javascript" src="test.js"></script> var script = document.createElement("script"); script.type = "text/javascript"; script.src= "test.js"; document.body.appendChild(script);//這句放哪均可以
在執行最後一行代碼把<script>元素添加到頁面中以前,是不會下載外部文件的。整個過程能夠用函數封裝:chrome
function loadScript(url){ var script = document.createElement('script'); script.type= "text/javascript"; script.src = url; document.body.appendChild(script); } loadScript("test.js");
加載完成後就能夠在頁面中其餘地方使用這個腳本了。怎麼知道腳本何時加載(從服務器請求下載過來了)完成了呢,有一些事件能夠探知,但要取決於瀏覽器,支持的瀏覽器少的可憐。
<script>(在<=IE10和Opera)和<link>(僅<=IE10)元素會觸發readystatechange事件(繼承自HTMLElement.prototype.onreadystatechange),能夠用來肯定外部JavaScript和Css文件是否已經加載完成。當把動態建立的元素添加到頁面中瀏覽器開始下載外部資源,當元素的readyState屬性不管等於「loaded」仍是「complete」都表示資源已經可用。下面給出一段加載外部JavaScript文件代碼(限在<=IE10且支持addEventListener中運行)。瀏覽器
window.onload = function(e){ var script = document.createElement('script'); script.addEventListener('readystatechange', function(e){ if(e.target.readyState == 'loaded' || e.target.readyState == 'complete'){ e.target.removeEventListener('readystatechange', arguments.callee, false); alert('Script loaded'); } }); script.src = 'example.js'; document.body.appendChild(script); }
此時獲取<script src="example.js">的readyState的值爲「loaded」,與此同時就能夠執行已經加載完的外部文件‘example.js’中的函數了。
(2)行內直接插入JS代碼(在除了<=IE8以外瀏覽器可運行)服務器
var script = document.createElement('script'); script.type = 'text/javascript'; script.appendChild(document.createTextNode("function sayHi(){alert('hi')}")); document.body.appendChild(script);
由於<=IE8將<script>視爲一個特殊的元素,不容許DOM訪問其子節點,不過可使用<script>元素text屬性(繼承自HTMLScriptElement.prototype)來指定JavaScript代碼。app
//針對<=IE8和Safari3及以後版本 var script = document.createElement('script'); script.type = 'text/javascript'; script.text = "function sayHi(){alert('hi')}"; document.body.appendChild(script);
兼容全部瀏覽器的代碼異步
function loadScriptString(code){ var script = document.createElement('script'); script.type = "text/javascript"; try{ //除過<=IE8和Safari3及以後版本 script.appendChild(document.createTextNode(code)); }catch(e){ script.text = code; } document.body.appendChild(script); }
實際上這樣執行代碼與在全局做用域中把相同的字符串傳遞給eval()是同樣的。
函數
動態樣式測試
可以把CSS樣式包含到HTML頁面中的元素有<link>和<style>
(1).動態樣式是指在頁面剛加載時不存在的樣式,動態樣式是在頁面加載完後動態添加到頁面中的。
function loadStyles(url){ var link = document.createElement("link"); link.rel = "stylesheet"; link.type = "text/css"; link.href = url; var head = document.getElementsByTagName('head')[0]; head.appendChild(link); }
加載外部樣式文件的過程是異步的,即加載樣式與執行JavaScript代碼的過程沒有固定次序。在<=IE10且支持addEventListener的IE中能夠利用幾種事件來檢測樣式是否加載完成
window.onload = function(e){ var link = document.createElement('link'); link.type = "text/css"; link.rel = "stylesheet"; link.addEventListener('readystatechange', function(e){ if(e.target.readyState == 'loaded' || e.target.readyState == 'complete'){ e.target.removeEventListener('readystatechange', arguments.callee, false); alert('css loaded'); } }); link.href ="example.css"; document.getElementsByTagName('head')[0].appendChild(link); }
此時獲取<link href="example.css">的readyState的值爲「complete」。
(2).使用<style>元素來包含嵌入式CSS
var style = document.createElement('style'); style.type = "text/css"; style.appendChild(document.createTextNode("body{background-color: red}")); var head = document.getElementsByTagName('head')[0]; head.appendChild(style);
一樣<=IE8將<style>視爲一個特殊的,與<script>相似的節點不容許訪問其子節點。解決這個問題就是訪問元素的styleSheet屬性(繼承自HTMLStyleElement.prototype),注意這個屬性只在<=IE10有,其餘瀏覽器(chrome和FF)經測試尚未,這個屬性指向一個CSSStyleSheet類型的一個實例。這個實例屬性又繼承了CSSStyleSheet.prototype的cssText屬性,該屬性值能夠接受CSS代碼。下圖測試結果爲IE10仿真。
兼容全部瀏覽器代碼
function loadStyleString(css){ var style = document.createElement('style'); style.type = "text/css"; try{ style.appendChild(document.createTextNode(css)); }catch(e){ style.styleSheet.cssText = css; } var head = document.getElementsByTagName("head")[0]; head.appendChild(style); }
注意經cssText設置以後,再經過style.styleSheet.cssText訪問該值時候返回的是大寫字符串,如圖
操做表格
爲方便構建表格,HTML DOM還爲<table>,<tbody>,<tr>元素添加了些屬性和方法。先來看看它們都有啥方法和屬性。
(1).table.__proto__->HTMLTableElement.prototype->HTMLElement.prototype->Element.prototype->Node.prototype->EventTarget.prototype->Object.prototype
(2).tbody.__proto__->HTMLTableSectionElement.prototype->HTMLElement.prototype->Element.prototype->Node.prototype->EventTarget.prototype->Object.prototype
(3).tr.__proto__->HTMLTableRowElement.prototype->HTMLElement.prototype->Element.prototype->Node.prototype->EventTarget.prototype->Object.prototype
//建立table var table = document.createElement('table'); table.border = 1; table.width = "100%"; //建立tbody var tbody = document.createElement("tbody"); table.appendChild(tbody); //建立第一行 tbody.insertRow(0); tbody.rows[0].insertCell(0); tbody.rows[0].cells[0].appendChild(document.createTextNode("cell 1,1")); tbody.rows[0].insertCell(1); tbody.rows[0].cells[1].appendChild(document.createTextNode("cell 1,2")); //建立第二行 tbody.insertRow(1); tbody.rows[1].insertCell(0); tbody.rows[1].cells[0].appendChild(document.createTextNode("cell 2,1")); tbody.rows[1].insertCell(1); tbody.rows[1].cells[1].appendChild(document.createTextNode("cell 2,2")); //表格添加到文檔中 document.body.appendChild(table);
使用NodeList
NodeList NamedNodeMap HTMLCollection 這三個集合都是動態的,除了有個例。
NodeList :getElementsByName,childNodes,querySelectorAll(靜態集合)等返回的都是NodeList實例
HTMLCollection:getElementsByTagName,getElementsByClassName,getElementsByTagNameNS,document.forms,document.children等返回的都是HTMLCollection實例
NamedNodeMap:表示屬性節點對象的集合,ele.attributes返回NamedNodeMap實例
訪問DOM文檔時實時運行的查詢,因此下面代碼會致使無限循環。
var divs = document.getElementsByTagName('div'),i,div; for(i = 0;i< divs.length; i++){ div = document.createElement('div'); document.body.appendChild(div); }
瀏覽器不會將建立的全部集合都保存在一個列表中,而是在下次訪問集合時再更新集合,i和divs.length每次都會同時遞增,結果它們的值永遠不會相等。正確寫法以下:
var divs = document.getElementsByTagName('div'),i,len,div; for(i = 0,len = divs.length; i<len;i++){ div = document.createElement('div'); document.body.appendChild(div); }
參考
《JavaScript高級程序設計》