DOM 编程入门
- DOM (Document Object Model) 文档对象模型
- 文档: 标记型文档(具有标签, 属性以及标签中封装的数据)
- 对象: 封装了属性和行为的实例, 可以被直接调用
- 模型: 所有标记型文档都具备一些共性特征的一个体现
- DOM 用来将标记型文档封装成对象, 并将标记型文档中的所有内容(标签, 文本, 属性等)都
封装成对象.封装成对象的目的是为了更为方便的操作这些文档以及文档中的所有内容.
因为对象的出现, 就可以有属性和行为被调用. - 只要是标记型文档, DOM 这种技术都可以对其进行操作.
- 要操作标记型文档,必须先对其进行解析.
- DOM 技术的解析方式:
- 首先将文件封装成 document 对象
- 然后按照标签的层次关系体现出标签的所属, 形成一个树状结构, 即 DOM 树
- 树中的标签以及文本甚至属性称为节点对象
- 标签通常称为页面中元素
- 这种 DOM 解析方式的好处: 可以对树中的节点进行任意操作, 比如: 增删改查
- 弊端: 这种解析需要将整个标记型文档加载进内存. 意味着如果标记型文档的体积很大, 较为浪费内存空间
- SAX 解析方式: 基于事件驱动的解析方式, 获取数据的速度很快, 但是不能对标记进行增删改
- DOM 技术的解析方式:
// 示例: DOM 解析方式
<html>
<head>
<title>这是演示文档</title>
</head>
<body>
<div>div区域</div>
<dl>
<dt>上层项目</dt>
<dd>下层项目</dd>
</dl>
<a href="www.sina.com">超链接</a>
<form>
<input type="text"/>
</form>
<table>
<tbody>
<tr>
<th>表头</th>
<td>单元格</td>
</tr>
</tbody>
</table>
</body>
</html>
DOM 模型有三种:
- DOM level 1: 将 html 文档封装成对象
- DOM level 2: 在 level 1 基础上加入了新功能, 比如解析名称空间 `xmlns`
- DOM level 3: 将 xml 文档封装成对象
BOM 模型
- Browser Object Model, 浏览器对象模型, 方便于操作浏览器
- 浏览器对应的对象就是 window 对象
- window 对象的子对象
- document : 代表给定浏览器窗口中的 html 文档
- navigator : 包含关于 web 浏览器的信息
- location : 包含关于当前 url 的信息
- history : 历史记录
- window 对象常用方法
confirm();
// 提示对话框, 返回值为布尔类型setTimeout();
// 经过指定的毫秒值后计算一个表达式, 返回一个 Integer 类型, TimeIDsetInterval();
// 每经过指定毫秒值后计算一个表达式, 返回一个 Integer 类型, TimeIDclearTimeout(TimeID);
// 取消先前用 Timeout() 方法设置的超时事件clearInterval(TimeID);
// 取消先前设置的间隔事件moveBy();
// 浏览器窗口移动指定的距离moveTo();
// 直接移动到指定的坐标点resizeBy();
// 缩放指定 x 和 y 偏移量resizeTo();
// 将窗口大小更改为指定的宽度和高度scrollBy();
// 操作滚动条scrollTo();
// 操作滚动条open();
// 打开close();
// 关闭窗口
- window 对象常用事件
onload();
// 在浏览器完成对象的加载后立即触发onunload();
// 在浏览器关闭结束后, 立即触发onbeforeunload();
// 在关闭浏览器, 浏览器还在的情况下触发
// 综合应用: 弹窗广告
// 思路: 页面一加载完就执行弹窗
// 在当前页面定义脚本, onload 事件中完成广告的弹窗
<script type="text/javascript">
// 页面一加载完, 执行下面脚本
// window.onload 中的 window 可以省略不写
onload = function(){
// 调用 open 方法, 打开弹窗广告页
open("广告页面","_blank","height=400,
width=400,status=no,toobar=no,menubar=no,location=no");
}
</script>
window 对象中的 document 对象
- document 对象将标记型文档进行了封装
- 该对象的作用, 是可以对标记型文档进行操作
- 最常见的操作就是, 获取页面中的节点.
因为想要实现动态效果, 需要对节点操作, 那么要先获取到这个节点.
要想获取节点,必须要先获取到节点所属的文档对象 document
document 对象中的方法:
- write()方法:
- 向页面输出值: `document.write("hello world!");`
- 向页面输出 html 代码: `document.write("<hr/>");`
- 获取节点的方法体现:
- `getElementById();` // 通过标签中的 id 属性值获取该标签节点, 返回该标签节点对象
- `getElementsByName();` // 通过标签的 name 属性获取节点, 因为 name 有可能相同, 所以返回的是一个数组
- `getElementsByTagName();` // 通过标签名获取节点, 因为标签名会重复, 所以返回的是一个数组
element 对象 (标签对象)
- 常用方法
- 获取属性里面的值: `getAttribute("属性名称");`
- 设置属性: `setAttribute(name,value);`
- 删除属性: `removeAttribute(name);`
Node 对象
- Node 对象是document 对象, 标签对象, 属性对象, 文本对象的父对象.
- 属性
- 节点名称(nodeName)
- 节点类型(nodeType)
- 节点值(nodeValue)
- 常见节点类型有三种:
- 标签型节点属于类型1
- 属性节点属于类型2
- 文本节点属于类型3
- 标签型节点是没有节点值的, 属性和文本节点可以有值.
- 通过节点的层次关系获取节点对象
- 父节点(
parentNode();
) : 一个节点的父节点只有一个. 一个父节点可以有多个儿子(是儿子, 不是孙子)节点 - 子节点(
childNodes();
) : 对应一个节点集合 - 上一个兄弟节点(
previousSibling();
) - 下一个兄弟节点(
nextSibling();
) - 注意: 获取标签下面子标签,应该尽量少用兄弟节点, 因为在解析的时候会出现浏览器不同,
解析不一致的情况,会解析出标签间的空白文本节点.而应该使用getElementsByTagName()
方法
- 父节点(
// 综合应用:
// 示例一: 创建并添加节点
<html>
<head>
<style type="text/css">
div {
border:#00ccff 1px solid;
width:200px;
padding:30px;
margin:10px;
}
#div_1{
background-color:#00ccff;
}
#div_2{
background-color:#FFccff;
}
#div_3{
background-color:#cc00ff;
}
#div_4{
background-color:#00FF00;
}
</style>
</head>
<body>
<script type="text/javascript">
// 创建并添加节点
// 需求一: 在 div_1 节点中添加一个文本节点
function crtAndAdd(){
/*
* 1. 创建一个文本节点
* 2. 获取 div_1 节点
* 3. 将文本节点添加到 div_1 节点中
*/
// 1.创建节点, 使用 document 中的 createTextNode 方法
// oTextNode 中 o 表示该变量是对象
var oTextNode = document.createTextNode("静夜思 李白");
// 2. 获取 div_1 节点
var oDivNode = document.getElementById("div_1");
// 3. 将文本节点添加到 div_1 节点中
oDivNode.appendChild(oTextNode);
}
// 需求二 : 在 div_1 中创建并添加一个按钮节点
function crtAndAdd_2(){
// 1. 创建一个按钮节点, 使用 document 的 createElement 方法
var oButNode = document.createElement("input");
// 设置 input 的属性 type 和 value
oButNode.type = "button";
oButNode.value = "李白";
// 2. 获取 div_1 节点
var oDivNode = document.getElementById("div_1");
// 3. 将按钮节点添加到 div_1 节点中
oDivNode.appendChild(oButNode);
}
// 方法二: 使用容器型标签中的一个属性, innerHTML, 该属性可以设置 html 文本
function crtAndAdd_3(){
// 获取 div_1 节点
var oDivNode = document.getElementById("div_1");
oDivNode.innerHTML = "<input type='button' value='李白'/>";
}
// 需求三: 删除 div_2 节点
function delNode(){
// 1. 获取 div_2 节点
var oDivNode = document.getElementById("div_2");
// 使用 removeChild() 方法, 删除子节点
// 首先获取 div_2 的父节点, 然后使用父节点的 removeChild(),
// 将 div_2 删除
oDivNode.parentNode.removeChild(oDivNode);
}
// 需求四: 使用 div_3 节点替换 div_1 节点
function updateNode(){
// 获取 div_1 和 div_3 节点
var oDivNode_1 = document.getElementById("div_1");
var oDivNode_3 = document.getElementById("div_3");
// 使用 replaceChild 方法
oDivNode_1.parentNode.relpaceChild(oDivNode_3,oDivNode_1);
}
// 需求五: 使用 div_3 节点替换 div_1, 并保留 div_3 节点
// 其实就是对 div_3 进行克隆, 然后替换
function cloneNode(){
// 获取 div_1 和 div_3 节点
var oDivNode_1 = document.getElementById("div_1");
var oDivNode_3 = document.getElementById("div_3");
// 克隆 div_3, true 表示带着其子节点一起复制
var oCopyNode_3 = oDivNode_3.cloneNode(true);
oDivNode_1.parentNode.replaceChild(oCopyNode_3);
}
</script>
<input type="button" value="创建并添加节点" onclick="crtAndAdd()" />
<input type="button" value="删除节点" onclick="delNode()"/>
<input type="button" value="修改节点" onclick="updateNode()"/>
<input type="button" value="克隆节点" onclick="cloneNode()" />
<br/>
<hr/>
<div id="div_1">
</div>
<div id="div_2">
床前明月光
</div>
<div id="div_3">
疑是地上霜
</div>
<div id="div_4">
举头望明月
</div>
</body>
</html>
**参考资料** - [JavaSE 基础视频(毕向东)](https://www.bilibili.com/video/av3143160/index_19.html#page=1) - [w3school DOM 对象](http://www.w3school.com.cn/jsref/dom_obj_document.asp)