BOM(Browser Object Model 浏览器物件模型)的重点在於浏览器的功能,完全由各家浏览器厂商自行开发。而DOM(Document Object Model 文件物件模型)则是W3C所制定的共同文件规范,提供跨浏览器且标准的文件处理介面。
DOM(Document Object Model 文件物件模型),是一个有阶层的树状结构,一个节点就是一个标签,根节点下有子节点,子节点下还有子节点,形成上下结构的关系,这样的树状结构,我们称之为「DOM Tree」。
《0陷阱!0误解!8天重新认识JavaScript》一书中有提到:
「DOM API定义了让JavaScript可以存取、改变HTML架构、样式和内容的方法,甚至对节点绑定的事件。」
当浏览器载入一个网页时,浏览器会分析这个网页的HTML,依照它的HTML结构建立一个DOM Tree。DOM的学习重点就在於掌握节点根结点之间的关系,学会如何控制DOM就可以控制网页,做出良好的互动体验。
如何透过DOM API取得节点:
//根据传入的id 名称,找到DOM里面相同id名称的节点。
document.getElementById('idName');
//根据传入的tag名称,回传所有符合条件的NodeList物件。
document.getEleMentsByTagName('tagName');
//根据传入的class名称,回传所有符合条件的NodeList物件。
document.getElementByClassName('className')
//根据所设定的selector条件(class或id都可以),回传第一个符合条件的节点。
document.querySelector('selector');
//根据所给定的selector条件,回传所有符合条件的 NodeList。
document.querySelectorAll;
假设网页上有一个h1的标签节点,里面没有任何内容:
<h1 id="hello"></h1>
我们利用document.getElementById('hello')来取得#hello节点,然後修改textContent属性:
document.getElementById('hello').textContent = '郭靖在华山论剑向大家说 Hello World!'
这就是取得节点,改变HTML内容的方法。
你有发现吗?不管是document.getElementById('idName') 或是document.querySelector('selector')都是由document开头。让我们来看看DOM Tree的图,可以发现document是整个DOM Tree的根结点,所以在存取DOM节点时,都要从document出发。
我们观察一下DOM Tree的图可以发现,节点之间有上下分层的关系,也有同一层节点间相邻的关系,所以节点与节点之间的关系可以区分为:
「所有的DOM节点物件都有childNodes属性,且这种属性无法修改」,那我们要如何知道一个节点是否有子节点? 这时候可以利用Node.hasChildNodes()来检查:
<div id="sword">
<ul>
<li>1 东邪</li>
<li>2 西毒</li>
<li>3 南帝</li>
<li>4 北丐</li>
<li>5 中神通</li>
</ul>
</div>
var node = document.getElementById('sword');
if(node.hasChildNodes()){
for(var i=0; i <node.childNodes.length; i++)
console.log(i + node.childNodes[i].nodeName);
}
来看一下console出来的结果:
cosole视窗中列出了查询的结果,我为查询的节点加上了编号,除了"LI"之外,还出现了"0#text"之类的字串,这是因为换行符号的空白节点也被查询了出来。如果不换行的话,"0#text"就不会出现。
Node.firstChild用来取得Node节点的第一个子节点,如果没有子节点的话,则回传null。而子节点包括空白节点,例如HTML Tag之间的换行符号。
<div id="sword">
<ul id="fiveHero"><li class="firstHero">1 东邪</li><li>2 西毒</li><li>3 南帝</li><li>4 北丐</li><li>5 中神通</li>
</ul>
</div>
var node = document.getElementById('fiveHero');
console.log(node.firstChild.className); //firstHero
Node.lastChild可以取得Node节点的最後一个子节点,如果没有子节点的话,则一样是传回null。而子节点包括空白节点,例如HTML Tag之间的换行符号。
<div id="sword">
<ul id="fiveHero"><li class="firstHero">1 东邪</li><li>2 西毒</li><li>3 南帝</li><li>4 北丐</li><li class="lastHero">5 中神通</li></ul>
</div>
var node = document.getElementById('fiveHero');
console.log(node.lastChild.className); //"lastHero"
Node.parentNode可以取得Node节点的父节点。
<div id="sword">
<ul id="fiveHero"><li class="firstHero">1 东邪</li><li>2 西毒</li><li>3 南帝</li><li>4 北丐</li><li class="lastHero">5 中神通</li></ul>
</div>
var node = document.getElementById('fiveHero');
console.log(node.parentNode.tagName); //"DIV"
有同一个父元素,位於同一层的节点称为「兄弟节点」,而Node.previousSibling可以取得Node节点的前一个兄弟节点。
<div id="sword">
<ul id="fiveHero">
<li class="firstHero">1 东邪</li><li class="secondHero">2 西毒</li><li class="thirdHero">3 南帝</li><li class="fifthHero">4 北丐</li><li class="lastHero">5 中神通</li>
</ul>
</div>
var node = document.querySelector('.secondHero');
console.log(node.previousSibling.className); //"firstHero"
Node.nextSibling可以取得Node节点的下一个兄弟节点。
<div id="sword">
<ul id="fiveHero">
<li class="firstHero">1 东邪</li><li class="secondHero">2 西毒</li><li class="thirdHero">3 南帝</li><li class="fifthHero">4 北丐</li><li class="lastHero">5 中神通</li>
</ul>
</div>
var node = document.querySelector('.secondHero');
console.log(node.nextSibling.className); //"thirdHero"
由上面几个操作,可以知道透过节点的抓取,我们可以取得节点的资讯,进而改变网页的结构、内容以及样式,懂得控制节点,就可以控制网页的呈现与使用者互动。
<<: Day06 - 监控 Sidekiq 有无正常运作(或执行超过多久)
天亮了 昨晚是平安夜 关於迷雾森林故事 焦虑抑制剂 10号:哈罗大家好,我是海马诚实小君,其实原本一...
从 2020 Day 21 - Replication 开始到现在,我们大多都是在谈系统出错了怎麽办...
这三小系列 本来我报名了软件开发组,但是我某天忘记发文了~ 所以再开了新系列拿个参加奖 Who Am...
提完了那麽多有关 APCS 的事,这次想要分析考 APCS 能够有怎样的好处。 权威性: APCS ...
前一篇物件侦测(4)停在 YOLOv1 的缺点上,现在就要来说 YOLOv2了! YOLOv2 YO...