DOM
什麼是DOM
document Object Model
專門操作網頁内容的API标準
W3C
為什麼
統一不同浏覽器操作網頁内容的API
用DOM操作網頁内容,幾乎所有浏覽器100%兼容
DOM Tree
網頁中一切内容都是節點(Node)對象
一切節點對象都存儲在一個樹型結構中
根節點
document
節點對象三大屬性
nodeType
節點的類型
何時
判斷節點類型
document 9 elem 1 attr 2 text 3
問題:
無法進一步判斷元素的名稱
解決
另見:
nodeName
節點名稱
何時
隻要進一步判斷元素的名稱
document #document elem 全大寫标簽名 attr 屬性名 text #text
nodeValue
節點值
document null elem null attr 屬性值 text 文本内容
DOM操作
構建DOM樹
查找觸發事件的元素
綁定事件
查找要操作的元素
修改
增加
删除
事件處理函數中的this
自動獲得觸發事件的當前元素
查找
不需要查找可直接獲得的節點
document
document.documentElement
html
document.head
document.body
document.forms[i/"id"]
form
按節點間關系查找
何時
已經獲得一個節點,要找周圍的相關節點時
節點樹
包含所有網頁内容(節點)的樹結構
2大類關系
1. 父子
elem.parentNode
最靠譜
elem.childNodes
*直接*子節點
elem.firstChild
elem.lastChild
2. 兄弟
elem.previousSibling
elem.nextSibling
優: 完整
問題:
受看不見的空字符的幹擾
解決
元素樹
僅包含元素節點的樹結構
不是一棵新樹,僅是節點樹的子集
何時
隻關心元素,不關心文本時
2大類關系
1. 父子
elem.parentElement
沒有node結尾
elem.children
IE8
elem.firstElementChild
elem.lastElementChild
2. 兄弟
elem.previousElementSibling
elem.nextElementSibling
優: 不受看不見的空字符的幹擾
缺: 不包含一切文本節點
可用.innerHTML
兼容性問題: IE9
childNodes和children
都返回動态集合(live collection)
不實際存儲數據,每次訪問集合,都重新查找DOM樹
優:
首次查找返回速度快
缺:
反複訪問集合,會導緻反複查找DOM樹
遍曆
for(var i=0,len=children.length;i<len;i )
遞歸遍曆
何時
隻要遍曆一個父節點下所有後代節點
如何
//Step1: 僅遍曆parent的直接子節點 function getChildren1(parent){ console.log(parent.nodeType!=3?parent.nodeName:parent.nodeValue); var children=parent.childNodes; for(var i=0,len=children.length;i<len;i ){ //Step2: 為每個子節點調用和父節點完全相同的函數 arguments.callee(children[i]); } }
深度優先遍曆
當同時有子節點和兄弟節點時,優先遍曆子節點。所有子節點遍曆完,才遍曆兄弟節點
問題: 遞歸的效率是極低
解決: 可用循環代替遞歸
function getChilddren2(parent){ //Step1: 創建叠代器對象 var iterator=document.createNodeIterator( parent, NodeFilter.SHOW_ALL , null, false .SHOW_ELEMENT ); var node; while((node=iterator.nextNode())!=null){ //node獲得當前正在遍曆的節點 console.log(node.nodeType!=3?node.nodeName:node.nodeValue); } }
問題:
隻能遍曆所有,如需篩選,得自己寫判斷
解決:
如何按條件查詢
按HTML查找
按id
var elem=document.getElementById("id")
返回一個元素對象
如果找不到,返回null
強調: 隻能用在document上
按标簽名
var elems=parent.getElementsByTagName("标簽名")
返回動态集合
如果找不到,返回空集合
強調:
可用在任意父節點上
不僅查找直接子節點,且查找所有後代節點
按name
var elems=document.getElementsByName("name")
強調:
隻能在document上調用
按class
var elems=parent.getElementsByClassName("class")
返回動态集合
如果找不到,返回空集合
強調:
可用在任意父節點上
不僅查找直接子節點,且查找所有後代節點
隻要class中包含指定的類名,就選擇
兼容性問題
IE9
問題:
一次隻能用一個條件查找,如果查找條件複雜時,會步驟繁瑣
按選擇器查找
Selector API
隻找一個
var elem=parent.querySelector("selector")
找所有符合條件的多個
var elems=parent.querySelectorAll("selector")
返回非動态集合
強調:
可在任意父元素上調用
受制于浏覽器對選擇器的兼容性
按HTML vs 按選擇器
1. 返回值:
按HTML
返回動态集合
selector API
返回非動态集合
直接存儲所有數據,反複訪問集合,不需要反複查找DOM樹
2. 首次查詢效率
按HTML更高
僅返回需要的内容,不需要準備完整數據
selector API低
第一次要返回完整數據
3. 易用性:
按HTML繁瑣
selector API簡單
何時
如果隻憑一個條件即可獲得想要的元素時,首選按HTML查找
如果需要多級複雜條件查找才能獲得想要的元素時,用selector API
修改
内容
.innerHTML
獲取或設置開始标簽到結束标簽之間的html代碼片段
.textContent
獲取或設置開始标簽到結束标簽之間的純文本内容
去掉所有标簽
翻譯轉義字符為正文
IE8:
.innerText
表單元素的内容
.value
屬性
标準屬性
核心DOM
操作一切結構化文檔的通用API
即可操作HTML,又可操作XML
獲取
了解
var attrNode=elem.attributes[i/屬性名] .getAttributeNode("屬性名")
var value=attrNode.value
var value=elem.getAttribute("屬性名")
修改
elem.setAttribute("屬性名",屬性值)
如果屬性不存在,也可set
判斷是否包含
var bool=elem.hasAttribute("屬性名")
移除
elem.removeAttribute("屬性名")
隻移除開始标簽中的attribute,不删除内存中對象的property
特點
優
萬能
缺
繁瑣
解決
HTML DOM
專門操作HTML文檔的簡化版API
隻對部分常用API進行簡化
如何
elem.屬性名
所有HTML标準屬性都被封裝在HTML DOM對象中,可直接用.訪問。用法普通對象的屬性完全一樣
特點:
優
簡單
缺
不是萬能
需要核心DOM的補充
狀态屬性
disabled, checked, selected
問題:
核心DOM不能操作:
解決:
HTML DOM
elem.狀态
.checked .selected .disabled
選擇器:
查找指定狀态的元素
:checked :selected :disabled
擴展(自定義)屬性
何時
代替id,元素,class選擇器,給多個元素添加行為
HTML DOM無法訪問擴展屬性
核心DOM
HTML5
定義:
data-屬性名="值"
訪問:
elem.dataset.屬性名
查找
CSS屬性選擇器
[data-屬性名=值]
樣式
内聯樣式:
elem.style.css屬性名
強調:
css屬性名要去橫線變駝峰
何時
專門用于修改内聯樣式
不影響其他元素的樣式
優先級最高
問題:
獲取時,隻能獲得内聯樣式
無法訪問從樣式表層疊或繼承來的完整樣式
解決
獲取一個元素計算後的完整樣式:
計算後的樣式:
最終應用到元素上的完整樣式
包括所有内聯,内部,外部樣式
将相對單位的值,計算為絕對單位
何時
隻要獲取樣式,就要獲取計算後的樣式
var style=getComputedStyle(elem對象)
var value=style.樣式屬性名
強調:
通過getComputedStyle獲得的樣式對象是隻讀
内部/外部樣式表
修改樣式表中的樣式
var sheet=document.styleSheets[i]
var rule=sheet.cssRules[i]
如果獲得的是keyframes,就需要繼續找子rule
rule.style.樣式屬性=值
最好的修改樣式的做法
修改class屬性,批量應用樣式
添加和删除
3步
創建新元素對象
var elem=document.createElement("标簽名")
設置關鍵屬性
将元素添加到DOM樹
parent.appendChild(child)
parent.insertBefore(child,oldChild)
parent.replaceChild(child,oldChild)
問題:
每操作一次DOM樹,都會導緻重新layout
解決
優化
盡量少的操作DOM樹
如果同時添加父元素和子元素
先在内存中将子元素添加到父元素
再将父元素一次性添加到DOM樹上
如果同時添加多個平級子元素
使用文檔片段
什麼是
内存中臨時存儲多個子元素的虛拟父元素
3步:
創建文檔片段
var frag=document.createDocumentFragment();
将子元素臨時添加到frag中
frag.appendChild(child)
将frag添加到DOM樹
parent.appendChild(frag)
強調:
frag不會成為頁面元素,添加子元素後,frag自動釋放
删除
parent.removeChild(child)
child.parentNode.removeChild(child)
HTML DOM常用對象
Image
var img=new Image();
Select/Option
屬性
value
當前選中項的value
如果選中項沒有value,則使用内容
selectedIndex
當前選中項的下标
options
獲得當前select下所有option的集合
length
相當于.options.length
獲得option的個數
清空option
.length=0
事件
onchange
當選中項發生改變時
方法
sel.add(option)
不支持文檔片段
sel.remove(i)
Option
創建
var opt=new Option(text,value)
屬性
text,value,index
Table/...
創建
var thead=.createTHead()
var tbody=.createTBody()
var tfoot=.createTFoot()
删除
.deleteTHead()
.deleteTFoot()
獲取
.tHead
.tBodies[i]
.tFoot
行分組
創建
var tr=.insertRow(i)
固定套路
1. 末尾追加一行: insertRow()
2. 開頭插入一行: insertRow(0)
删除
.deleteRow(i)
問題
i無法自動獲得
解決
首選
table.deleteRow(tr.rowIndex)
獲取
.rows
tr
創建
var td=.insertCell(i)
删除
.deleteCell(i)
獲取
.cells
删除行
行分組.deleteRow(i)
i是相對于當前行分組内的位置
table.deleteRow(tr.rowIndex)
rowIndex是相對于整個表中的位置
Form
獲取:
var form=document.forms[i/id]
屬性:
.elements
獲得所有表單元素的集合
input textarea select button
.length
.elements.length
獲得所有表單元素的個數
方法:
form.submit()
代替submit按鈕,在程序中手動提交表單
Element
獲得表單中的元素
獲得任意表單元素:
form.elements[i/id/name]
如果表單元素有name屬性
form.name
方法
.focus()
.blur()
事件
onsubmit
在最終提交表單之前觸發
,
更多精彩资讯请关注tft每日頭條,我们将持续为您更新最新资讯!