概述
DOM 的概念
• 文档对象模型(Document Object Model,简称 DOM),是 W3C 组织推荐的处理可扩展标记语言的标准编程接口。它是一种与平台和语言无关的应用程序接口(API),它可以动态地访问程序和脚本,更新其内容、结构和 www 文档的风格(目前,HTML 和 XML 文档是通过说明部分定义的)。文档可以进一步被处理,处理的结果可以加入到当前的页面。DOM 是一种基于树的 API 文档,它要求在处理过程中整个文档都表示在存储器中。
DOM 树
• DOM 又称为文档树模型
• - 文档:一个网页可以称为文档
• - 节点:网页中的所有内容都是节点(标签、属性、文本、注释等)
• - 元素:网页中的标签
• - 属性:标签的属性
DOM 经常进行的操作
• 获取元素
• 对元素进行操作(设置其属性或调用其方法)
• 动态创建元素
• 事件(什么时机做相应的操作)
DOM 获取页面元素
获取页面元素
• 为什么要获取页面元素?
• 例如:我们想要操作页面上的某部分(显示/隐藏,动画),需要先获取到该部分对应的元素,才进行后续操作。
根据 id 获取元素
• 方法:调用 document 对象的 getElementById 方法。
• 参数:字符串类型的 id 的属性值。
• 返回值:对应 id 名的元素对象。
• 注意1:由于 id 名具有唯一性,部分浏览器支持直接使用 id 名访问元素,但不是标准方式,不推荐使用。
• 注意2:代码执行顺序,如果 js 在 html 结构之前,会导致结构未加载,不能获取对应id的元素。
• 注意3:id名具有唯一性,同时书写两个相同的id名,只会执行第一个。
根据标签名获取元素
• 方法:调用 document 对象的 getElementsByTagName 方法。
• 参数:字符串类型的标签名。
• 返回值:同名的元素对象组成的数组。
• 注意1:操作数据时需要按照操作数组的方法进行。
• 注意2:getElementsByTagName 方法内部获取的元素是动态增加的。
元素对象内部获取标签元素
• 获取的元素对象内部,本身也可以调用根据标签获取元素方法,例如 div 元素对象也可以调用 getElementsByTagName 方法。
• 目的:缩小选择元素的范围,类似 css 中的后代选择器
根据 name 获取元素
• 方法:调用 document 对象的 getElementsByName 方法。
• 参数:字符串类型的 name 属性值。
• 返回值:name 属性值相同的元素对象组成的数组。
• 不建议使用:在 IE 和 Opera 中有兼容问题,会多选中 id 属性值相同的元素。
Nodelist :节点(标签、属性、文本、注释等) 列表集合,类数组
方法选中的元素也是动态变化的
根据类名获取元素
• 方法:调用 document 对象的 getElementsByClassName 方法。
• 参数:字符串类型的 class 属性值。
• 返回值:class 属性值相同的元素对象组成的数组。
• 浏览器兼容问题:不支持 IE8 及以下的浏览器
方法选中的元素也是动态变化的
根据选择器获取元素
• 方法1:调用 document 对象的 querySelector 方法,通过 css 中的选择器去选取第一个符合条件的标签元素。
• 方法2:调用 document 对象的 querySelectorAll 方法,通过 css 中的选择器去选取所有符合条件的标签元素。
• 参数:字符串类型的 css 中的选择器。
• 浏览器兼容问题:不支持 IE8 以下的浏览
必须在结构加载完成后书写,不能写在前面。
总结
掌握,没有兼容问题
• getElementById()
• getElementsByTagName()
了解
• getElementsByName()
• getElementsByClassName()
• querySelector()
• querySelectorAll()
DOM 事件基本应用
事件
• 事件:在什么时候做什么事
• 执行机制:触发–响应机制
• 绑定事件(注册事件)三要素:
1、事件源:给谁绑定事件
2、事件类型:绑定什么类型的事件 click 单击
3、事件函数:事件发生后执行什么内容,写在函数内部
事件监听
• JavaScript 解析器会给有绑定事件的元素添加一个监听,解析器会一直监测这个元素,只要触发对应的绑定事件,会立刻执行事件函数。
常用事件监听方法
• 方法1:绑定 HTML 元素属性。
• 方法2:绑定 DOM 对象属性
常用的鼠标事件类型
• onclick 鼠标左键单击触发
• ondbclick 鼠标左键双击触发
• onmousedown 鼠标按键按下触发
• onmouseup 鼠标按键放开时触发
• onmousemove 鼠标在元素上移动触发
• onmouseover 鼠标移动到元素上触发
• onmouseout 鼠标移出元素边界触发
案例:
• 点击按钮弹出提示框
DOM 元素属性操作
非表单元素的属性
• 例如:href、title、id、src 等。
• 调用方式:元素对象打点调用属性名,例如 obj.href。
• 注意:部分的属性名跟关键字和保留字冲突,会更换写法。
- class → className
- for → htmlFor
- rowspan → rowSpan
• 属性赋值:给元素属性赋值,等号右侧的赋值都是字符串格式。
案例
•点击按钮切换图片
• 点击按钮显示隐藏 div
• 美女相册
获取标签内部内容的属性
• 获取标签内部内容的属性有两个:innerHTML 和 innerText
• innerHTML属性,在获取标签内部内容时,如果包含标签,获取的内容会包含标签,获取的
内容包括空白换行等。
• innerText属性,在获取标签内部内容时,如果包含标签,获取的内容会过滤标签,获取的
内容会去掉换行和缩进等空白。
更改标签内容
还可以通过两个属性给双标签内部去更改内容:
• innerHTML 设置属性值,有标签的字符串,会按照 HTML 语法中的标签加载。
• innerText 设置属性值,有标签的字符串,会按照普通的字符加载。
对比使用场景
• innerText:在设置纯字符串时使用。
• innerHTML:在设置有内部子标签结构时使用。
表单元素属性
• value 用于大部分表单元素的内容获取(option除外)
• type 可以获取input标签的类型(输入框或复选框等)
• disabled 禁用属性
• checked 复选框选中属性
• selected 下拉菜单选中属性
• 注意:在 DOM 中元素对象的属性值只有一个时,会被转成布尔值显示。
例如:txt.disabled = true;
案例
• 检测用户名是否是3-6位,密码是否是6-8位,如果不满足要求高亮显示文本框
• 设置下拉框中的选中项
• 搜索文本框
• 全选反选
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title></title>
<style>
* {
padding: 0;
margin: 0;
}
.wrap {
width: 300px;
margin: 100px auto 0;
}
table {
border-collapse: collapse;
border-spacing: 0;
border: 1px solid #c0c0c0;
width: 300px;
}
th,
td {
border: 1px solid #d0d0d0;
color: #404060;
padding: 10px;
}
th {
background-color: #09c;
font: bold 16px "微软雅黑";
color: #fff;
}
td {
font: 14px "微软雅黑";
}
tbody tr {
background-color: #f0f0f0;
}
tbody tr:hover {
cursor: pointer;
background-color: #fafafa;
}
</style>
</head>
<body>
<div class="wrap">
<table>
<thead>
<tr>
<th>
<input type="checkbox" id="all" />
</th>
<th>商品</th>
<th>价钱</th>
</tr>
</thead>
<tbody id="tb">
<tr>
<td>
<input type="checkbox" />
</td>
<td>iPhone8</td>
<td>8000</td>
</tr>
<tr>
<td>
<input type="checkbox" />
</td>
<td>iPad Pro</td>
<td>5000</td>
</tr>
<tr>
<td>
<input type="checkbox" />
</td>
<td>iPad Air</td>
<td>2000</td>
</tr>
<tr>
<td>
<input type="checkbox" />
</td>
<td>Apple Watch</td>
<td>2000</td>
</tr>
</tbody>
</table>
<input type="button" value=" 反 选 " id="btn">
</div>
<script>
// 获取元素
var all = document.getElementById("all");
var tb = document.getElementById("tb");
var btn = document.getElementById("btn");
var tb_inputs = tb.getElementsByTagName("input");
// 1.全选:让子选项的选择效果始终与全选保持一致
all.onclick = function() {
// 遍历所有的子选项
for (var i = 0; i < tb_inputs.length; i++) {
// 让每一个子选项的 checked 属性值与全选保持一致
tb_inputs[i].checked = all.checked;
}
};
// 2.单独选择子选项过程
// 给每一次点击任何一个子选项进行判断
for (var i = 0; i < tb_inputs.length; i++) {
tb_inputs[i].onclick = function() {
// 需要判断所有的子选项是否都是选中的状态,如果都选中,让全选被选中,如果有的没有被选中,让全选取消选择
allChecked();
}
}
// 3.反选
btn.onclick = function() {
// 让所有子选项与之前的状态相反
for (var i = 0; i < tb_inputs.length; i++) {
// 让属性值取原来相反的值
tb_inputs[i].checked = !tb_inputs[i].checked;
}
// 控制全选效果,也需要进行取反
allChecked();
};
// 定义一个 all 是否被选中的函数
function allChecked() {
// 使用一个中间过渡变量,初始认为所有的子选项都是被选中的
var isAllChecked = true;
// 遍历所有子选项,进行判断
for (var j = 0; j < tb_inputs.length; j++) {
// 一旦有一个是没有被选择的,让变量变为 false
if (tb_inputs[j].checked === false) {
isAllChecked = false;
// 只要走到这里,说明肯定不是全选,不需要往下执行循环
break;
}
}
// 如果循环内部条件永远不成立,说明所有子选项都是被选中,isAllChecked 的值没有发生变化,还是 true
// 给 all 元素设置 checked 属性
all.checked = isAllChecked;
}
</script>
</body>
</html>
自定义属性操作
• getAttribute(name) 获取标签行内属性
• setAttribute(name,value) 设置标签行内属性
• removeAttribute(name) 移除标签行内属性
• 与element.属性的区别: 上述三个方法用于获取任意的行内属性,包括自定义的属性。
style 样式属性操作
• 使用 style 属性方式设置的样式显示在标签行内。
• element.style 属性的值,是所有行内样式组成的一个样式对象。
• 样式对象可以继续点语法调用或更改 css 的行内样式属性,例如 width、height 等属性。
• 注意1:类似 background-color 这种复合属性的单一属性写法,是由多个单词组成的,要
修改为驼峰命名方式书写 backgroundColor。
• 注意2:通过样式属性设置宽高、位置的属性类型是字符串,需要加上 px 等单位。
className 类名属性操作
• 修改元素的 className 属性相当于直接修改标签的类名。
• 如果需要修改多条 css 样式,可以提前将修改后的样式设置到一个类选择器中,后续通过
修改类名的方式,批量修改 css 样式。
案例
• 开关灯
function my$(id) {
return document.getElementById(id);
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<input type="button" value="关灯" id="btn">
<script src="common.js"></script>
<script>
// 获取元素
var btn = my$("btn");
// console.log(btn);
// 定义一个判断变量,true 表示开灯状态,false 表示关灯状态
// var isOpen = true;
// 点击事件,控制 body 的背景
btn.onclick = function () {
// 开灯时,需要点击后让它关灯并切换文字为 开灯
// if (isOpen) {
// document.body.style.backgroundColor = "black";
// this.value = "开灯";
// isOpen = false;
// } else {
// document.body.style.backgroundColor = "white";
// this.value = "关灯";
// isOpen = true;
// }
// 直接使用 btn 的 value 值进行判断
if (this.value === "关灯") {
document.body.style.backgroundColor = "black";
this.value = "开灯";
} else {
document.body.style.backgroundColor = "white";
this.value = "关灯";
}
};
</script>
</body>
</html>
• 显示隐藏二维码
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title></title>
<style>
.box {
width: 50px;
height: 50px;
background: url(images/bgs.png) no-repeat -159px -51px;
position: fixed;
right: 10px;
top: 40%;
}
.erweima {
position: absolute;
top: 0;
left: -150px;
}
.box a {
display: block;
width: 50px;
height: 50px;
}
.hide {
display: none;
}
.show {
display: block;
}
</style>
</head>
<body>
<div class="box" id="box">
<div class="erweima hide" id="er">
<img src="images/456.png" alt=""/>
</div>
</div>
<script src="common.js"></script>
<script>
// 获取元素
var box = my$("box");
var er = my$("er");
// 给 box 添加鼠标移上事件 onmouseover ,添加鼠标离开事件 onmouseout
box.onmouseover = function () {
// 让子级元素进行显示,就是将 hide 改为 show
// er.className = "erweima show";
er.className = er.className.replace("hide","show");
};
box.onmouseout = function () {
// 让子级元素进行隐藏,就是将 show 改为 hide
// er.className = "erweima hide";
er.className = er.className.replace("show","hide");
};
</script>
</body>
</html>
• 当前输入的文本框高亮显示
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<input type="text"><br>
<input type="text"><br>
<input type="text"><br>
<input type="text"><br>
<input type="text"><br>
<input type="text"><br>
<input type="text"><br>
<button id="btn">按钮</button>
<script>
// 获取元素
var txts = document.getElementsByTagName("input");
// 添加批量的获取焦点事件
for (var i = 0; i < txts.length; i++) {
// 排他思想:1.排除其他 2.保留自己
// 给每一个input标签添加获取焦点事件
txts[i].onfocus = function() {
// 排除其他的方法:将所有的项包含自己都设置为默认样式
// 遍历数组,让所有的样式恢复默认
for (var j = 0; j < txts.length; j++) {
txts[j].style.backgroundColor = "";
}
// 设置元素自己高亮显示
// 保留自己的特殊样式
// this 指代事件源自己
this.style.backgroundColor = "yellow";
};
}
</script>
</body>
</html>
• 点击按钮改变div的大小和位置
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<style>
div {
width: 100px;
height: 100px;
background-color: pink;
}
.new {
position: absolute;
width: 200px;
height: 200px;
left: 200px;
top: 200px;
}
</style>
</head>
<body>
<input type="button" value="按钮" id="btn">
<div id="box"></div>
<script src="common.js"></script>
<script>
//获取元素
var btn = my$("btn");
var box = my$("box");
// 添加事件
btn.onclick = function() {
// 修改类名
// box.className = "new";
// 修改 style 样式对象中的属性
box.style.width = "200px";
box.style.height = "200px";
box.style.left = "200px";
box.style.top = "200px";
box.style.position = "absolute";
};
</script>
</body>
</html>
• 表格隔行变色、高亮显示
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<style>
td {
width: 100px;
height: 40px;
}
</style>
</head>
<body>
<table border="1" style="border-collapse: collapse;">
<tr>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
</table>
<script>
// 获取所有的行
var trs = document.getElementsByTagName("tr");
// 1.隔行变色
for (var i = 0; i < trs.length; i++) {
// 下标为偶数的行显示粉色
// 下标为奇数的行显示灰色
if (i % 2 == 0) {
trs[i].style.backgroundColor = "pink";
} else {
trs[i].style.backgroundColor = "lightgray";
}
// 2.鼠标移上高亮显示,鼠标离开恢复默认
// 全局变量
var bgc;
// 鼠标移上高亮显示
trs[i].onmouseover = function() {
// 定义变量记录 tr 原来的颜色
bgc = this.style.backgroundColor;
this.style.backgroundColor = "skyblue";
};
// 鼠标离开恢复默认
trs[i].onmouseout = function() {
this.style.backgroundColor = bgc;
};
}
</script>
</body>
</html>
• tab选项卡切换
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title></title>
<style>
* {margin:0; padding: 0;}
ul {
list-style-type: none;
}
.box {
width: 400px;
height: 300px;
border: 1px solid #ccc;
margin: 100px auto;
overflow: hidden;
}
.hd {
height: 45px;
}
.hd span {
display:inline-block;
width: 90px;
background-color: pink;
line-height: 45px;
text-align: center;
cursor: pointer;
}
.hd span.current {
background-color: skyblue;
}
.bd div {
height: 255px;
background-color: skyblue;
display: none;
}
.bd div.current {
display: block;
}
</style>
</head>
<body>
<div class="box">
<div class="hd" id="hd">
<span class="current">体育</span>
<span>娱乐</span>
<span>新闻</span>
<span>综合</span>
</div>
<div class="bd" id="bd">
<div class="current">我是体育模块</div>
<div>我是娱乐模块</div>
<div>我是新闻模块</div>
<div>我是综合模块</div>
</div>
</div>
<script src="common.js"></script>
<script>
// 获取元素
var hd = my$("hd");
var spans = hd.getElementsByTagName("span");
var bd = my$("bd");
var divs = bd.getElementsByTagName("div");
// 鼠标移上某个 span 让它添加一个类名,其他的失去类名
for (var i = 0 ; i < spans.length ; i++) {
// 给每一个 span 元素添加一个新的属性,记录自己在数组中的下标
spans[i].index = i;
spans[i].onmouseover = function () {
// console.dir(this);
// 1.让 span 自己进行切换
// 排他思想:
// 排除其他
for (var j = 0; j < spans.length ; j++) {
spans[j].className = "";
// 由于 divs 中数据个数与 spans 一样,所以可以再同一个遍历循环中,进行排他操作
divs[j].className = "";
}
// 保留自己
this.className = "current";
// console.log(this.index);
// 2.让 bd 中的 div 也对应进行切换
// 对应控制思想:有两组数据中存储了相同个数的元素对象,一组对象的变化,会引起另外一组的变化
// 实现方法:找两个数据中的共同点,两个数组中元素对象的下标是一样的
// 对应控制中也会涉及到排他的操作
// 保留 div 自己的类名
divs[this.index].className = "current";
};
}
</script>
</body>
</html>
DOM 节点操作
节点属性
• nodeType 节点的类型,属性值为数字,表示不同的节点类型,共 12 种,只读
1 元素节点
2 属性节点
3 文本节点
• nodeName 节点的名称(标签名称),只读
• nodeValue 节点值,返回或设置当前节点的值
元素节点的 nodeValue 始终是 null
父子节点常用属性
• childNodes 只读属性,获取一个节点所有子节点的实时的集合,集合是动态变化的。
• children 只读属性,返回一个节点所有的子元素节点集合,是一个动态更新的 HTML 元素
集合。
• firstChild 只读属性,返回该节点的第一个子节点,如果该节点没有子节点则返回 null。
• lastChild 只读属性,返回该节点的最后一个子节点,如果该节点没有子节点则返回 null。
• parentNode 返回一个当前节点的父节点,如果没有这样的节点,比如说像这个节点是树结构
的顶端或者没有插入一棵树中,这个属性返回 null。
• parentElement 返回当前节点的父元素节点,如果该元素没有父节点,或者父节点不是一个 DOM
元素,则返回 null
兄弟节点常用属性
• nextSibling 只读属性,返回与该节点同级的下一个节点,如果没有返回null。
• previousSibling 只读属性,返回与该节点同级的上一个节点,如果没有返回null。
• nextElementSibling 只读属性,返回与该节点同级的下一个元素节点,如果没有返回null。
• previousElementSibling 只读属性,返回与该节点同级的上一个元素节点,如果没有返回null。
• 注意:nextElementSibling 和 previousElementSibling 有兼容性问题,IE9以后才支持。
创建新节点的方法
• document.createElement(“div”) 创建元素节点
• document.createAttribute(“id”) 创建属性节点
• document.createTextNode(“hello”) 创建文本节点
• 一般将创建的新节点存在变量中,方便使用。
节点常用操作方法 1
• parentNode.appendChild(child):将一个节点添加到指定父节点的子节点列表末尾。
• parentNode.replaceChild(newChild, oldChild):用指定的节点替换当前节点的一个子节
点,并返回被替换掉的节点。
• parentNode.insertBefore(newNode, referenceNode):在参考节点之前插入一个拥有指定
父节点的子节点,referenceNode 必须设置,如果 referenceElement 为 null 则 newNode
将被插入到子节点的末尾。
• parentNode.removeChild(child):移除当前节点的一个子节点。这个子节点必须存在于当
前节点中。
节点常用操作方法 2
• Node.cloneNode():克隆一个节点,并且可以选择是否克隆这个节点下的所有内容。参数为
Boolean 布尔值,表示是否采用深度克隆,如果为 true,则该节点的所有后代节点也都会被
克隆,如果为 false,则只克隆该节点本身,默认值为 true,节点下的内容会被克隆。
• 注意:克隆时,标签上的属性和属性值也会被复制,写在标签行内的绑定事件可以被复制,
但是通过。
节点常用操作方法 3
• Node.hasChildNodes():没有参数,返回一个 Boolean 布尔值,来表示该元素是否包含有
子节点。
• Node.contains(child):返回一个 Boolean 布尔值,来表示传入的节点是否为该节点的后
代节点。
判断方法总结
• 有三种方法可以判断当前节点是否有子节点。
• node.firstChild !== null
• node.childNodes.length > 0
• node.hasChildNodes()
案例应用
• 动态创建列表
• 动态创建表格
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
table{
border-collapse: collapse;
}
thead{
background-color: #ccc;
}
th,td{
width: 100px;
height: 40px;
text-align: center;
}
</style>
</head>
<body>
<h1>动态创建表格</h1>
<table id="wrap" border="1">
<thead>
<tr>
<th>姓名</th>
<th>科目</th>
<th>成绩</th>
<th>操作</th>
</tr>
</thead>
<tbody id="tb">
</tbody>
</table>
<script src="common.js"></script>
<script>
// 获取元素
var tb = my$("tb");
// 模拟后台传输的数据
var datas = [
{name: "zs",subject: "语文",score: 80},
{name: "ls",subject: "数学",score: 87},
{name: "ww",subject: "英语",score: 90},
{name: "lb",subject: "物理",score: 89},
{name: "cc",subject: "生物",score: 100},
{name: "sq",subject: "化学",score: 98}
];
// 根据数组中的数据个数生成对应个数的 tr
// 将生成 tr 添加到 tbody 中
// 数组遍历
for (var i = 0 ; i < datas.length ; i++) {
// 每一个数据都要生成一个 tr
var tr = document.createElement("tr");
// 添加到 tb 中
tb.appendChild(tr);
// 每一个 tr 中还需要添加对应的 td
// 每一行 内部的 td 中的数据来自于 数组的每一项
var data = datas[i]; //{name: "zs",subject: "语文",score: 80}
// 遍历 data 对象,根据它的项数来确定添加的 td 的个数
for (var k in data) {
// 生成一个 td
var td = document.createElement("td");
// 添加到 tr 中去
tr.appendChild(td);
// 添加给每一个 td 数据
td.innerText = data[k];
}
// 除了前面动态获取的数据 td 之外,还要添加一个删除的 td
td = document.createElement("td");
// 添加到 tr 中去
tr.appendChild(td);
// 最后一个 td 中需要添加一个 a 标签
var a = document.createElement("a");
a.innerText = "删除";
a.href = "javascript:void(0);"
// 将 a 添加到 td 中
td.appendChild(a);
// 给生成的每个 a 添加一个点击事件,移除当前所在的行
a.onclick = function () {
// 找到所在的行的 tr
// this.parentNode.parentNode
// 从 tbody 中移除对应的 tr
tb.removeChild(this.parentNode.parentNode);
};
}
</script>
</body>
</html>
• 选择水果
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
select {
width: 200px;
height: 200px;
background-color: #33cccc;
font-size: 20px;
}
</style>
</head>
<body>
<select id="all" size="5" multiple="multiple">
<option>苹果</option>
<option>橘子</option>
<option>梨</option>
<option>西瓜</option>
<option>水蜜桃</option>
</select>
<input type="button" value=">>" id="btn1">
<input type="button" value="<<" id="btn2">
<input type="button" value=">" id="btn3">
<input type="button" value="<" id="btn4">
<select id="choose" multiple="multiple">
</select>
<script src="common.js"></script>
<script>
// 获取元素
var all = my$("all");
var choose = my$("choose");
var btn1 = my$("btn1");
var btn3 = my$("btn3");
// 给第一个按钮添加点击事件,让 all 中的所有子元素移动到 choose 中
btn1.onclick = function() {
var opts = all.children; //内部的元素时动态添加的
// 获取 all 中所有的子元素
// 获取最开始的数组的个数
var n = opts.length;
// console.log(n);
// 将所有的 opts 中的元素添加给 choose
for (var i = 0; i < n; i++) {
choose.appendChild(opts[0]);
}
};
// 单选移动
btn3.onclick = function() {
var opts = all.children; //内部的元素时动态添加的
// 移动的内容希望可以是固定的一个数组中的项
var arr = [];
// 通过判断条件,往 arr 中添加需要移动的元素
for (var i = 0; i < opts.length; i++) {
if (opts[i].selected === true) {
arr.push(opts[i]);
}
}
// 对需要移动的固定数组进行遍历
for (var j = 0; j < arr.length; j++) {
choose.appendChild(arr[j]);
arr[j].selected = false;
}
};
</script>
</body>
</html>
DOM 事件详解
注册事件的其他方法1
• element.addEventListener() 方法。
• 参数:
第一个参数:事件类型的字符串(直接书写”click”,不需要加 on)
第二个参数:事件函数
• 同一个元素可以多次绑定事件监听,同一个事件类型可以注册多个事件函数
• 兼容性问题:不支持 IE9 以下的浏览器
注册事件的其他方法2
• element.attachEvent() 方法。
• 参数:
第一个参数:事件类型的字符串(需要加 on)
第二个参数:事件函数
• 同一个元素可以多次绑定事件监听,同一个事件类型可以注册多个事件函数
• 兼容性问题:只支持 IE10 及以下的浏览器。
注册事件的兼容写法
• 自定义一个注册事件函数
• 参数:事件源,事件类型(不加 on),事件函数
• IE9 及以上的浏览器,使用 addEventListener 方法
• IE9 以下的浏览器,使用 attachEvent 方法
• 判断浏览器时,不需要判断它的版本,可以检测浏览器能力
• 浏览器能力检测:将某个方法的调用作为 if 语句的判断条件,如果浏览器认识该方法返回
true,否则返回 false。
移除事件的其他方法1
• element.removeEventListener() 方法。
• 参数:
第一个参数:事件类型的字符串(直接书写”click”,不需要加 on)
第二个参数:事件函数引用名
• 注意:没有办法移除一个匿名函数,所以在注册事件时需要单独声明一个有函数名的事件函数。
• 兼容性问题:不支持 IE9以下的浏览器
移除事件的其他方法2
• element.detachEvent() 方法。
• 参数:
第一个参数:事件类型的字符串(需要加 on)
第二个参数:事件函数
• 注意:没有办法移除一个匿名函数,所以在注册事件时需要单独声明一个有函数名的事件函数。
兼容性问题:只支持 IE10 及以下的浏览器
移除事件的兼容写法
• 自定义一个移除事件函数
• 参数:事件源,事件类型(不加 on),事件函数
• IE9 及以上的浏览器,使用 removeEventListener 方法
• IE9 以下的浏览器,使用 detachEvent 方法
• 建议:将自己封装的一些常用函数和方法,放到一个单独的 .js 文件中
DOM 事件流
事件流的三个阶段
• 第一个阶段:事件捕获
• 第二个阶段:事件执行过程
• 第三个阶段:事件冒泡
• addEventListener() 第三个参数为 false 时,事件冒泡
• addEventListener() 第三个参数为 true 时,事件捕获
• onclick 类型:只能进行事件冒泡过程,没有捕获阶段
• attachEvent() 方法:只能进行事件冒泡过程,没有捕获阶段
事件委托
• 利用事件冒泡,将子级的事件委托给父级加载
• 同时,需要利用事件函数的一个 e 参数,内部存储的是事件对象
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<style>
* {
margin: 0;
padding: 0;
}
ul {
width: 300px;
border: 1px dashed #f0f;
margin: 50px auto;
font-size: 24px;
line-height: 48px;
list-style: none;
}
li {
padding-left: 20px;
cursor: pointer;
}
</style>
</head>
<body>
<ul id="list">
<li>刘亦菲</li>
<li>杨幂</li>
<li>唐嫣</li>
<li>赵丽颖</li>
<li>刘诗诗</li>
</ul>
<script>
// 让每个 li 被点击后,自己添加特殊的背景色,而其他兄弟不添加
// 以前的思路:获取所有的 li 标签元素,批量添加事件
// 事件委托:可以将一些子级的公共类型的事件委托给他们的父级添加,在父级内部想办法找到真正触发事件的最底层的事件源
// 获取元素
var list = document.getElementById("list");
var lis = list.children;
// 给 ul 添加点击事件
list.onclick = function (e) {
// 在内部要想办法找到真正触发事件的 li
// 借用事件函数内部的一个参数 e,e 是事件对象
// 只要触发事件,函数内部都可以得到一个事件对象,对象中存储了关于事件的一系列数据
// e.target 属性记录的就是真正触发事件的事件源
// 排除其他
for (var i = 0 ; i < lis.length ; i++) {
lis[i].style.backgroundColor = "";
}
e.target.style.backgroundColor = "pink";
};
</script>
</body>
</html>
事件对象
• 只要触发事件,就会有一个对象,内部存储了与事件相关的数据。
• e 在低版本浏览器中有兼容问题,低版本浏览器使用的是 window.event
• 事件对象常用的属性:
e.eventPhase 查看事件触发时所处的阶段
e.target 用于获取触发事件的元素
e.srcElement 用于获取触发事件的元素,低版本浏览器使用
e.currentTarget 用于获取绑定事件的事件源元素
e.type 获取事件类型
e.clientX/e.clientY 所有浏览器都支持,鼠标距离浏览器窗口左上角的距离
e.pageX/e.pageY IE8 以前不支持,鼠标距离整个HTML页面左上顶点的距离
案例
• 图片跟随鼠标移动效果
取消默认行为和阻止事件传播的方式
• e.preventDefault() 取消默认行为
• e.returnValue 取消默认行为,低版本浏览器使用
• e.stopPropagation(); 阻止冒泡,标准方式
• e.cancelBubble = true; 阻止冒泡,IE 低版本,标准中已废弃
其他事件类型
• MDN web 事件参考:https://developer.mozilla.org/zh-CN/docs/Web/Events
DOM 特效
DOM 提供了一套与元素自身有关的位置
和大小的属性。
偏移量属性
• offsetParent 偏移参考父级,距离自己最近的有定位的父级,如果都没有定位参考body(html)
• offsetLeft/offsetTop 偏移位置
• offsetWidth/offsetHeight 偏移大小
客户端大小
• client 系列没有参考父级元素。
• clientLeft/clientTop 边框区域尺寸,不常用
• clientWidth/clientHeight 边框内部大小
滚动偏移属性
• scrollLeft/scrollTop 盒子内部滚动出去的尺寸
• scrollWidth/scrollHeight 盒子内容的宽度和高度
案例
• 拖拽案例
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title></title>
<style>
* {
margin: 0;
padding: 0;
}
.nav {
height: 30px;
background: #036663;
border-bottom: 1px solid #369;
line-height: 30px;
padding-left: 30px;
}
.nav a {
color: #fff;
text-align: center;
font-size: 14px;
text-decoration: none;
}
.d-box {
width: 400px;
height: 300px;
border: 5px solid #eee;
box-shadow: 2px 2px 2px 2px #666;
position: absolute;
top: 40%;
left: 40%;
background-color: white;
/* 不让文字被选中 */
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
.hd {
width: 100%;
height: 25px;
background-color: #7c9299;
border-bottom: 1px solid #369;
line-height: 25px;
color: white;
cursor: move;
}
#box_close {
float: right;
cursor: pointer;
}
</style>
</head>
<body>
<div class="nav">
<a href="javascript:;" id="register">注册信息</a>
</div>
<div class="d-box" id="d_box">
<div class="hd" id="drop">注册信息 (可以拖拽)
<span id="box_close">【关闭】</span>
</div>
<div class="bd"></div>
</div>
<script src="common.js"></script>
<script>
// 获取元素
var box = document.getElementById("d_box");
var drop = document.getElementById("drop");
var close = document.getElementById("box_close");
// 给 drop 添加鼠标按下事件,在内部继续绑定一个鼠标移动事件
drop.onmousedown = function(e) {
e = e || window.event;
// 记忆鼠标按下时,鼠标在父盒子内部的间距
var l = e.pageX - box.offsetLeft;
var t = e.pageY - box.offsetTop;
// 鼠标移动事件
drop.onmousemove = function(e) {
e = e || window.event;
// 鼠标移动过程中,可以计算 box 的 left 和 top
var nowleft = e.pageX - l;
var nowtop = e.pageY - t;
// 赋值给 box 的样式属性
box.style.left = nowleft + "px";
box.style.top = nowtop + "px";
};
};
// 鼠标弹起事件
drop.onmouseup = function() {
drop.onmousemove = null;
};
// 点击 关闭 box
close.onclick = function() {
box.style.display = "none";
};
</script>
</body>
</html>
• 弹出登录窗
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title></title>
<style>
.login-header {
width: 100%;
text-align: center;
height: 30px;
font-size: 24px;
line-height: 30px;
}
ul,
li,
ol,
dl,
dt,
dd,
div,
p,
span,
h1,
h2,
h3,
h4,
h5,
h6,
a {
padding: 0px;
margin: 0px;
}
.login {
width: 512px;
position: absolute;
border: #ebebeb solid 1px;
height: 280px;
left: 50%;
right: 50%;
background: #ffffff;
box-shadow: 0px 0px 20px #ddd;
z-index: 9999;
margin-left: -256px;
margin-top: 140px;
display: none;
}
.login-title {
width: 100%;
margin: 10px 0px 0px 0px;
text-align: center;
line-height: 40px;
height: 40px;
font-size: 18px;
position: relative;
cursor: move;
-moz-user-select: none;
/*火狐*/
-webkit-user-select: none;
/*webkit浏览器*/
-ms-user-select: none;
/*IE10*/
-khtml-user-select: none;
/*早期浏览器*/
user-select: none;
}
.login-input-content {
margin-top: 20px;
}
.login-button {
width: 50%;
margin: 30px auto 0px auto;
line-height: 40px;
font-size: 14px;
border: #ebebeb 1px solid;
text-align: center;
}
.login-bg {
width: 100%;
height: 100%;
position: fixed;
top: 0px;
left: 0px;
background: #000000;
filter: alpha(opacity=30);
-moz-opacity: 0.3;
-khtml-opacity: 0.3;
opacity: 0.3;
display: none;
}
a {
text-decoration: none;
color: #000000;
}
.login-button a {
display: block;
}
.login-input input.list-input {
float: left;
line-height: 35px;
height: 35px;
width: 350px;
border: #ebebeb 1px solid;
text-indent: 5px;
}
.login-input {
overflow: hidden;
margin: 0px 0px 20px 0px;
}
.login-input label {
float: left;
width: 90px;
padding-right: 10px;
text-align: right;
line-height: 35px;
height: 35px;
font-size: 14px;
}
.login-title span {
position: absolute;
font-size: 12px;
right: -20px;
top: -30px;
background: #ffffff;
border: #ebebeb solid 1px;
width: 40px;
height: 40px;
border-radius: 20px;
}
</style>
</head>
<body>
<div class="login-header"><a id="link" href="javascript:void(0);">点击,弹出登录框</a></div>
<div id="login" class="login">
<div id="title" class="login-title">登录会员
<span><a id="closeBtn" href="javascript:void(0);" class="close-login">关闭</a></span>
</div>
<div class="login-input-content">
<div class="login-input">
<label>用户名:</label>
<input type="text" placeholder="请输入用户名" name="info[username]" id="username" class="list-input">
</div>
<div class="login-input">
<label>登录密码:</label>
<input type="password" placeholder="请输入登录密码" name="info[password]" id="password" class="list-input">
</div>
</div>
<div id="loginBtn" class="login-button"><a href="javascript:void(0);" id="login-button-submit">登录会员</a></div>
</div>
<!-- 遮盖层 -->
<div id="bg" class="login-bg"></div>
<script>
// 获取元素
var link = document.getElementById("link");
var login = document.getElementById("login");
var bg = document.getElementById("bg");
var closeBtn = document.getElementById("closeBtn");
// 添加 link 的点击事件,让登录窗口和遮盖层显示
link.onclick = function () {
login.style.display = "block";
bg.style.display = "block";
};
// 添加 btn 的点击事件,让登录窗口和遮盖层隐藏
closeBtn.onclick = function () {
login.style.display = "none";
bg.style.display = "none";
};
</script>
</body>
</html>
最后
以上就是害羞翅膀为你收集整理的DOM——文档对象模型的全部内容,希望文章能够帮你解决DOM——文档对象模型所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复