一文学「DOM」 - 含案例展示

* 什么是DOM

DOM 是 Document Object Model(文档对象模型)的缩写, 是中立于平台和语言的接口,它允许程序和脚本动态地访问和更新文档的内容、结构和样式;

DOM 标准被分为 3 个不同的部分:

  • 核心 DOM - 针对任何结构化文档的标准模型。
  • XML DOM - 针对 XML 文档的标准模型。定义了所有 XML 元素的对象和属性,以及访问它们的方法
  • HTML DOM - 针对 HTML 文档的标准模型。 定义了所有 HTML 元素的对象和属性,以及访问它们的方法

这里我们只讲HTML DOM。

* HTML DOM 树

HTML DOM 将 HTML 文档视作树结构。这种结构被称为节点树:



通过 HTML DOM,树中的所有节点均可通过 JavaScript 进行访问。所有 HTML 元素(节点)均可被修改,也可以创建或删除节点.

那么,什么是节点?
在 HTML DOM 中,所有事物都是节点。

  • 整个文档就是一个文档节点。 <html>...</html>
  • 每个HTML元素是元素节点。 <head>...</head><body>...</body><div>...</div>
  • HTML元素内部的文本是文本节点 / TextNode。 <p>hello world</p> 中的 hello world
  • 每个HTML属性是属性节点。 <div class="mystyle"></div> 中的 class
  • 注释是注释节点。

例子: <title>你好!</title>,元素节点 <title>,包含值为 "你好!" 的文本节点。

* HTML DOM 对象 - 方法和属性

方法 是我们可以在节点上执行的动作(比如添加或修改元素),属性 是我们能够获取或设置的值(比如节点的名称或内容)。

常用的 HTML DOM 方法:

  • getElementById(id) - 获取带有指定 id 的节点(元素) var ele = document.getElementById("eleId");
  • appendChild(node) - 插入新的子节点(元素)ele.appendChild(sub);
  • removeChild(node) - 删除指定的子节点(元素)ele.removeChild(sub);
  • insertBefore(node) - 在指定的子节点前面插入新的子节点(元素);相对兄弟元素定位
  • getAttribute("id") - 返回指定的属性值 ele.getAttribute("id");
  • setAttribute("id") - 把指定属性设置或修改为指定的值 ele.setAttribute("disabled") = "true";

  • getElementsByTagName() - 返回包含带有指定标签名称的所有元素的节点列表(集合/节点数组)
  • getElementsByClassName() - 返回包含带有指定类名的所有元素的节点列表
  • replaceChild() - 替换子节点
  • createAttribute() - 创建属性节点;为一个元素增加一个属性
  • createElement() - 创建元素节点
  • createTextNode() - 创建文本节点

常用的HTML DOM属性:

  • innerHTML - 节点(元素)的文本值 var text = ele.innerHTML
  • parentNode - 节点(元素)的父节点 var eleParent = ele.parentNode 父节点只有一个,没有s
  • childNodes - 节点(元素)的子节点 var eleChild = ele.childNodes 子节点有可能有多个,带s
  • attributes - 节点(元素)的属性节点 var attr - ele.attributes 获取dom属性列表

我做了实验,发现非常有意思的信息:
html代码

<div class="box" id="box">
  <div class="main" id="main"></div>
  <div class="sub" id="sub">nihao</div>
</div>

css代码

* {margin: 0px; padding: 0px;}
.box {
  width: 300px;
  height: 300px;
  background-color: #c688e3;
  margin: 0 auto;
  position: relative;
}
.main {
  width: 100px;
  height: 100px;
  margin: 0 auto;
  background: #40cfee;
}
.sub {
  width: 100px;
  height: 100px;
  margin-top: 100px;
  position: absolute;
  background-color: pink;
}

javascript代码

var box = document.getElementById("box");
var main = document.getElementById("main");

var sub = document.getElementById("sub");

// main.appendChild(sub);    
// main.removeChild(sub);
console.dir(box.childNodes);
// console.dir(sub.attributes);

效果图

原始效果

mainsubbox包含框中按文档普通流规则正常显示。

main.appendChild(sub)效果

subappendChildmain内部,作为main的子元素而存在。注意,此时sub是在文档普通流中提出来之后加入到main中的,作为main的兄弟节点的sub已经被提走了。

先appendChild后又removeChild的效果

可以看到,sub节点没了,虽然他作为子元素本身存在与在box包含框中,但经过appendChildremoveChild之后,该节点已经被删除。

原始状态打印box.childNodes

惊了,居然length为5!为什么长度为5?细细看来发现,第0/2/4都为text,并且打开看发现值是 回车键,明白了吧,原因就是我们在编程时习惯给格式化,对代码进行换行显示,这个换行符其实就是个不可见文本,dom会将其当做子元素了,所以长度为5。所以平时我们在使用的时候一定要注意,并且也可以用这种方式获取文本内容。

原始状态打印box.attributes

这个没什么问题,就是正常的将属性抓取出来,放到一个数组当中而已。

innerHtml属性

innerHTML 属性对于获取或替换 HTML 元素的内容(文本节点)
html代码

<html>
  <body>
    <p id="intro">Hello World!</p>
  </body>
</html>

css代码

#intro {
  display: none;
}

javascript代码

var txt=document.getElementById("intro").innerHTML;
document.write(txt);

效果展示

利用document.write()在页面上打印出文本节点

将javascript代码改一下,如下
javascript代码

document.getElementById("intro").innerHTML = "haha, is me";
var txt=document.getElementById("intro").innerHTML
document.write(txt)

效果展示

通过innerHTML修改了文本节点

nodeName属性

nodeName 属性规定节点的名称,并且,nodeName 始终包含 HTML 元素的大写字母标签名

  • nodeName 是只读的
  • 元素节点的 nodeName 与标签名相同
  • 属性节点的 nodeName 与属性名相同
  • 文本节点的 nodeName 始终是 #text
  • 文档节点的 nodeName 始终是 #document

nodeValue 属性

nodeValue 属性规定节点的值
-元素节点的 nodeValue 是 undefined 或 null
-文本节点的 nodeValue 是文本本身
-属性节点的 nodeValue 是属性值 document.getElementById("main").nodeValue 输出 null
html代码

<html>
  <body>
    <p id="intro">Hello World!</p>
  </body>
</html>

css代码

#intro {
  display: none;
}

js代码

var txt = document.getElementById('intro').nodeValue;
var f = txt == undefined
document.write(f)

效果展示

页面打印出 true

页面代码

<html>
  <body>
    <p id="intro">Hello World!</p>
    <script>
      x=document.getElementById("intro");
      document.write(x.firstChild.nodeValue);
    </script>
  </body>
</html>

输出

通过firstChild属性找到第一个子节点,这里是个文本节点

nodeType 属性

nodeType 属性返回节点的类型,在我们爬数据的时候可能会用到。重要的有以下几种:

元素类型 nodeType
元素 1
属性 2
文本 3
注释 8
文档 9

* HTML DOM 访问

访问HTML元素,就是访问HTML 节点,三种方法:

  • getElementById() 方法 document.getElementById("intro"); 返回带有指定 ID 的元素
  • getElementsByTagName() 方法 document.getElementsByTagName("p");返回带有指定标签名的所有元素
  • getElementsByClassName() 方法 document.getElementsByClassName("intro");返回带有相同类名的**所有 **HTML 元素
    getElementsByClassName() 在 Internet Explorer 5,6,7,8 中无效。

* HTML DOM 修改

修改 HTML DOM 意味着许多不同的方面

  • 改变 HTML 内容 document.getElementById("p1").innerHTML="New text!";改变一个 <p> 元素的 HTML 内容
  • 改变 CSS 样式 document.getElementById("p2").style.color="blue";改变一个<p>元素 文字的颜色
  • 改变 HTML 属性
  • 创建新的 HTML 元素 见下方
  • 替换已有的 HTML 元素 ```见下方``
  • 删除已有的 HTML 元素
  • 改变事件(处理程序) 见下方

创建新的 HTML 元素(1)
如需向 HTML DOM 添加新元素,您首先必须创建该元素(元素节点),然后把它追加到已有的元素上。

html代码

<div id="d1">
  <p id="p1">This is a paragraph.</p>
  <p id="p2">This is another paragraph.</p>
</div>

javascript代码

var para=document.createElement("p");  // 创建<p>元素节点
var node=document.createTextNode("This is new.");  // 给空的<p>元素节点增加文本节点"this is new"
para.appendChild(node);  // 生成带有文本子节点的<p>元素节点

var element=document.getElementById("d1");
element.appendChild(para);  // 追加<p>元素节点到d1中

页面展示

新的p元素已经被成功插入

上面的代码是将新元素添加到最后一个子节点后面的,如果我们不希望如此,也可以用insertBefore() 实现;

创建新的 HTML 元素(2)
这里涉及到三个元素节点,父元素,新元素和某个兄弟元素。
html代码

<div id="div1">
  <p id="p1">This is a paragraph.</p>
  <p id="p2">This is another paragraph.</p>
</div>

javascript代码

var para=document.createElement("p");    // 创建<p>元素节点
var node=document.createTextNode("This is new.");   // 给空的<p>元素节点增加文本节点"this is new"
para.appendChild(node);     // 生成带有文本子节点的<p>元素节点

var element=document.getElementById("div1");  // 查找父节点的元素节点
var child=document.getElementById("p1");  // 查找插入位置的元素节点
element.insertBefore(para,child);     // 将para元素节点插入child元素节点之前

替换 HTML 元素replaceChild()

html代码

<div id="div1">
  <p id="p1">This is a paragraph.</p>
  <p id="p2">This is another paragraph.</p>
</div>

javascript代码

var para=document.createElement("p");
var node=document.createTextNode("This is new.");
para.appendChild(node);

var parent=document.getElementById("div1");
var child=document.getElementById("p1");
parent.replaceChild(para,child);   // 使用replaceChild()替换

使用事件修改dom元素

HTML DOM 允许您在事件发生时执行代码;当 HTML 元素”有事情发生“时,浏览器就会生成事件:

  • 在元素上点击
  • 加载页面
  • 改变输入字段

html代码

<html>
  <body>
    <input type="button" onclick="ChangeBackground()" value="Change background color" />
  </body>
</html>

js代码

function ChangeBackground() 
{
  document.body.style.backgroundColor="lavender";
}

效果展示

点击修改背景颜色

* HTML DOM 事件

HTML DOM 允许 JavaScript 对 HTML 事件作出反应,当事件发生时,可以执行 JavaScript。
HTML 事件的例子:

  • 当用户点击鼠标时 onclick="doIt()";鼠标按下onmousedown;鼠标弹起onmouseup。首先当某个鼠标按钮被点击时,触发 onmousedown 事件,然后,当鼠标按钮被松开时,会触发 onmouseup 事件,最后,当鼠标点击完成时,触发 onclick 事件
  • 当网页已加载时 onload="doIt()";离开网页时使用 onunload="doIt()"onload 事件可用于检查访客的浏览器类型和版本,以便基于这些信息来加载不同版本的网页。onloadonunload 事件可用于处理 cookies
  • 当图片已加载时
  • 当鼠标移动到元素上时 onmouseover=”doIt()“;鼠标移开onmouseout=”doIt()“
  • 当输入字段被改变时 onchange="doIt()" 常用于输入字段的监控,验证。
  • 当 HTML 表单被提交时
  • 当用户触发按键时

我们也可以使用 HTML DOM 来分配事件:
该例为 button 元素分配 onclick 事件:
javascript代码

document.getElementById("myBtn").onclick=function(){
  displayDate()
};

用onload来处理cookies
html代码

<html>
  <body onload="checkCookies()">
    <p>弹出的提示框会告诉你浏览器是否已启用 cookie。</p>
  </body>
</html>

javascript代码

function checkCookies() {
  if (navigator.cookieEnabled==true) {
      alert("Cookies are enabled")
    } else {
      alert("Cookies are not enabled")
    }
}

* HTML DOM - 导航

1. HTML DOM 节点列表

getElementsByTagName() 方法返回节点列表数组
下面的代码选取文档中的所有 <p> 节点:

var x=document.getElementsByTagName("p");

可以通过下标号访问这些节点。如需访问第二个 <p>,您可以这么写:

var y=x[1];   // 下标从0开始

length 属性定义节点列表中节点的数量

var len = x.length

简单应用: 获取所有 <p> 元素节点,并输出每个 <p> 元素的文本节点的值

x=document.getElementsByTagName("p");
for (i=0;i<x.length;i++) {
  document.write(x[i].innerHTML);
  document.write("<br />");
}
2. 导航节点关系

您能够使用三个节点属性:parentNode、firstChild 以及 lastChild ,在文档结构中进行导航。

<html>
  <body>
    <p>Hello World!</p>
    <div>
      <p>DOM 很有用!</p>
      <p>本例演示节点关系。</p>
    </div>
  </body>
</html>

观察上述结构

  • 首个 <p> 元素是 <body> 元素的首个子元素(firstChild)firstChild 属性可用于访问元素的文本,前面我们用过
  • <div> 元素是 <body> 元素的最后一个子元素(lastChild)
  • <body> 元素是首个 <p> 元素和 <div> 元素的父节点(parentNode)
3. DOM 根节点

这里有两个特殊的属性,可以访问全部文档:

  • document.documentElement - 全部文档
  • document.body - 文档的主体 页面的<body>部分

html代码

<html>
  <body>
    <p>Hello World!</p>
    <div>
      <p>DOM 很有用!</p>
      <p>本例演示 <b>document.body</b> 属性。</p>
    </div>
  </body>
</html>

javascript代码

alert(document.body.innerHTML);

效果展示

alert弹出内容

4. childNodes 和 nodeValue

html代码

<html>
  <body>
    <p id="intro">Hello World!</p>
  </body>
</html>

javascript代码

var txt=document.getElementById("intro").childNodes[0].nodeValue;
document.write(txt);

效果展示

页面本身一个 / document.write一个

* 结束语

至此,HTML DOM 内容已经结束,如果理解还不够透彻,你可以猛戳这里查看更多DOM实例

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,937评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,503评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,712评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,668评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,677评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,601评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,975评论 3 396
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,637评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,881评论 1 298
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,621评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,710评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,387评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,971评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,947评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,189评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,805评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,449评论 2 342

推荐阅读更多精彩内容

  • 之前通过深入学习DOM的相关知识,看了慕课网DOM探索之基础详解篇这个视频(在最近看第三遍的时候,准备记录一点东西...
    微醺岁月阅读 4,449评论 2 62
  • 本章内容 理解包含不同层次节点的 DOM 使用不同的节点类型 克服浏览器兼容性问题及各种陷阱 DOM 是针对 HT...
    闷油瓶小张阅读 623评论 0 1
  • 一、JS前言 (1)认识JS 也许你已经了解HTML标记(也称为结构),知道了CSS样式(也称为表示),会使用HT...
    凛0_0阅读 2,752评论 0 8
  • 楊龍賢2013年書於香港,記載當時沒有工作也找不到工作的我。 港中乘船渡綠浪, 浪頂白沫招我蕩, 不因吾有自盡願,...
    杨龙儿阅读 212评论 0 0
  • 多年后 希望有一间木屋 木屋前种着花树 花树下有一把靠椅 靠椅上有两位白发老人 他们岁月静好 他们浅笑安然
    七lyf阅读 108评论 0 0