DOM基础语法
DOM基础语法
1、 简介
文档对象模型(DOM),是 W3C 组织推荐的处理可扩展标记语言(HTML、XML)的标准编程接口
W3C 已经定义了一系列 DOM 接口,通过这些 DOM 接口可以改变网页的内容、结构和样式
1.1 DOM树
文档:一个页面就是一个文档,DOM 中使用 document 表示
元素:页面中的所有标签都是元素,DOM 中使用 element 表示
节点:网页中的所有内容都是节点(标签、属性、文本、注释等),DOM 中使用 node 表示
DOM把以上内容都看做是对象
2、 获取元素
获取页面中的元素可以使用一下几种方式
- 根据 id 获取
- 根据标签名获取
- 通过 HTML5 新增的方法获取
- 特殊元素获取
2.1 根据 id 获取
使用 getElementById("id")
方法可以获取带有 id 的元素对象
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div id="time"> 2022-2-1</div>
<script>
var time = document.getElementById("time"); // 大小写敏感
console.log(typeof time);
console.dir(time);
console.log(time); // console.dir() 打印我们返回的元素对象,更好的查看里面的属性和方法
</script>
</body>
</html>
- 因为我们的文档页面从上往下加载,所以先得有标签,故我们 script 写到标签的下面
- get 获得 element 元素 by 通过 驼峰命名法
- 参数 id 是大小写敏感的字符串
- 返回的是一个元素对象
2.2 根据标签名获取
使用getElementsByTagName("标签名")
方法可以返回带有指定标签名的对象集合
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<ul>
<li>123 a</li>
<li>123 b</li>
<li>123 c</li>
<li>123 d</li>
<li>123 e</li>
</ul>
<script>
var lis = document.getElementsByTagName("li");
console.log(lis);
console.log(lis[0]);
for (var i = 0; i < lis.length(); i++){
console.log(lis[i])
}
</script>
</body>
</html>
- 返回的是获取过来元素对象的集合,以伪数组的形式存储,遍历获取数据
- 得到的元素是动态的
- 如果页面中没有这个元素,放回的伪数组是一个空数组
2.3 根据标签名获取
使用element.getElementByTagName("标签名")
获取某个元素(父元素)内部所有指定标签名的子元素
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<ul>
<li>123 a</li>
<li>123 b</li>
<li>123 c</li>
<li>123 d</li>
<li>123 e</li>
</ul>
<ol id="first">
<li>23 a</li>
<li>23 b</li>
<li>23 c</li>
<li>23 d</li>
<li>23 e</li>
</ol>
<script>
var ol1 = document.getElementById("first"); // var ol1 = document.getElementsByTagName("ol")[0] 效果一样
var lis = ol1.getElementsByTagName("li"); // 一定要指明那个父元素
console.log(lis);
console.log(lis[0]);
</script>
</body>
</html>
父元素必须是单个对象(必须指明是哪个元素对象)获取的时候不包括父元素自己
2.4 根据 类名来获取
使用document.getElementsByClassName("类名")
来获取元素对象集合
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div class="box">盒子1</div>
<div class="box">盒子2</div>
<script>
var boxs = document.getElementsByClassName("box");
console.log(boxs);
</script>
</body>
</html>
2.5 通过指定选择器获取
使用document.querySelector("选择器")
指定选择器,获取第一个元素对象
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div class="box">盒子1</div>
<div class="box">盒子2</div>
<div id="f1">盒子3</div>
<script>
var box = document.querySelector("div");
console.log(box);
var id = document.querySelector("#f1"); // 使用id选择
// 如果使用类选择器,则 (".box")
console.log(id);
</script>
</body>
</html>
使用document.querySelectorAll("选择器")
指定选择器,获取所有的元素
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div class="box">盒子1</div>
<div class="box">盒子2</div>
<div id="f1">盒子3</div>
<script>
var boxs = document.querySelectorAll(".box");
console.log(boxs);
</script>
</body>
</html>
2.6 获取 body 和 html 元素
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script>
// body
var bodyEle = document.body;
console.log(bodyEle);
console.dir(bodyEle);
// html
var htmlEle = document.documentElement;
console.log(htmlEle);
</script>
</body>
</html>
3、 事件基础
3.1 概述
JS 使我们有能力创建动态页面,而事件是可以被 JS 侦测到的行为
简单理解:触发 --- 响应机制
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<button id="btn">hello</button>
<script>
btn.onclick = function() {
alert("hello world");
}
</script>
</body>
</html>
- 事件是有三部分组成:事件源、事件类型、事件处理程序;也称事件三要素
- 事件源:事件被触发的对象
- 事件类型:如何触发,什么事件,如:鼠标点击、鼠标经过还是键盘按下
- 事件处理程序:通过一个函数赋值的方式完成
3.2 事件执行步骤
- 获取事件源
- 注册事件(绑定事件)
- 添加事件处理程序(采取函数赋值形式)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div>点我</div>
<script>
// 获取事件源
var div = document.querySelector("div");
// 绑定事件,并且添加事件处理程序
div.onclick = function(){
alert("你好呀!")
}
</script>
</body>
</html>
3.3 常见的鼠标事件
鼠标事件 | 触发条件 |
---|---|
onclick | 单击 |
ondblclick | 双击 |
onmousedown | 鼠标上的按钮被按下触发的事件 |
onmouseup | 鼠标按下后,松开时触发的事件 |
onmouseover | 鼠标悬浮 |
onmousemove | 鼠标移动 |
onmouseenter | 鼠标进入 |
onmouseleave | 鼠标离开 |
onfocus | 鼠标焦点 |
onblur | 失去鼠标焦点 |
4、 操作元素
JS 的 DOM 操作可以改变网页的内容、结构和样式,我们可以利用 DOM 操作元素来改变元素里面的内容、属性等
4.1 改变元素内容
element.innerText; // 从起始位置到终止位置的内容,当它不包括html标签,同时空格和换行也会换掉
element.innerHTML; // 起始位置到终止位置的全部内容,包括html标签,同时保留空格和换行
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<button>显示当前时间</button>
<div>时间显示</div>
<script>
var btn = document.querySelector("button"); // 获取对象
var div = document.querySelector("div"); // 获取div
btn.onclick = function(){ // 定义事件
var date = new Date();
var year = date.getFullYear();
var month = date.getMonth() + 1;
var data = date.getDate();
var hour = date.getHours();
var mit = date.getMinutes();
var sec = date.getSeconds();
div.innerText = year.toString() + "-" + month.toString() + "-" + data.toString() + '\n' + hour.toString() + ":" + mit.toString() + ":" + sec.toString(); // 修改文本
}
</script>
</body>
</html>
- innerText 和 innerHTML 的区别
- innerText 不识别HTML标签,而 innerHTML 则识别
- innerText 会去除换行和空格
4.2 改变元素属性
直接赋值即可
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<button id="btn1">百度</button>
<button id="btn2">qq</button>
<a href="https://www.baidu.com">使用百度</a>
<script>
var btn1 = document.querySelector("#btn1"), // 获取按钮1
btn2 = document.querySelector("#btn2"),
link = document.querySelector("a");
btn1.onclick = function(){
link.href = "https://www.baidu.com"; // 修改属性
link.innerText = "使用百度";
}
btn2.onclick = function(){
link.href = "https://www.qq.com";
link.innerText = "使用qq";
}
</script>
</body>
</html>
4.3 表单元素属性操作
利用 DOM 可以操作如下表单元素的属性
type / value / checked / selected / disabled
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<button>按钮</button>
<input type="text" placeholder="请输入内容">
<script>
var btn = document.querySelector("button");
var ipt = document.querySelector("input");
// 定义事件
btn.onclick = function(){
ipt.value = "你好呀!" // input 表单专门使用 value 来修改
btn.disabled = true; // 点击按钮后禁用,也可以用于表单禁用
// 也可以使用 this.disabled = true; 来实现按钮的禁用 this指向的是函数的调用者
}
</script>
</body>
</html>
显示密码
- 点击按钮,把密码框的类型改为文本框就可以看见里面的代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<button>按钮</button>
<input type="password" placeholder="请输入密码">
<script>
var btn = document.querySelector("button");
var ipt = document.querySelector("input");
// 定义事件
var flag = 0;
btn.onclick = function(flag){
flag++;
if (flag % 2 === 0 ){
ipt.type = "password";
}
else{
ipt.type = "text";
}
}
</script>
</body>
</html>
4.4 样式属性操作
我们可以通过 JS 修改元素的大小、颜色、位置等样式
element.style 行内样式属性操作
element.style.cssText 多个行内样式的修改
element.className 类名样式操作
4.4.1 行内样式
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
#div {
width: 200px;
height: 200px;
background-color: pink;
}
</style>
</head>
<body>
<div id="div">你好</div>
<script>
var div = document.querySelector("#div");
div.onclick = function() { // 行内
div.style.backgroundColor = "purple"; // 属性采取驼峰命名法
this.style.height = "100px";
}
div.ondblclick = function() { // 行内多个修改
this.style.cssText = "background-color: red; height: 30px";
}
</script>
</body>
</html>
注意
- JS 里面的样式采取驼峰命名法
- 多个修改里面每个单词使用
-
隔开- JS 修改 style 样式操作,产生的是行内样式,CSS 权重比较高
- 样式比较少或者功能简单的情况下使用
4.4.2 类名样式
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
#div {
width: 200px;
height: 200px;
background-color: pink;
}
.change {
background-color: purple;
color: red;
font-size: large;
margin: 100px;
}
</style>
</head>
<body>
<div id="div">文本</div>
<script>
var div = document.querySelector("#div");
div.onclick = function() {
this.className = 'change'; // 让我们当前元素的类名改为了 change
}
</script>
</body>
</html>
注意
className 会直接更改元素的类名,会覆盖原先的类名
可以通过修改元素的 className 更改元素的样式,适合于样式较多或者功能复杂的情况
如果想要保留原先的类名,我们可以这么做
this.className = "原先的类名 change";
4.5 排他思想
如果有同一组元素,我们想要某一个元素实现某个样式,需要用到循环的排他思想算法
- 所有元素全部清除样式
- 给当前元素设置样式
- 注意顺序不能颠倒
4.6 表单全选与取消全选
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
.wrap > table > thead {
background-color: rgb(22, 99, 102);
}
.wrap > table{
margin: 100px auto;
}
</style>
</head>
<body>
<div class="wrap">
<table border="1" cellspacing="0" cellpadding="3px">
<thead>
<tr>
<th>
<input type="checkbox" id="j_cbAll">
</th>
<th>goods</th>
<th>price</th>
</tr>
</thead>
<tbody id="j_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>
</div>
<script>
var j_cbAll = document.getElementById("j_cbAll");
var j_tbs = document.getElementById("j_tb").getElementsByTagName("input");
j_cbAll.onclick = function(){
for (var i = 0; i < j_tbs.length; i++){
j_tbs[i].checked = this.checked; // this.checked 表示选中
}
}
for (var i = 0; i < j_tbs.length; i++){
j_tbs[i].onclick = function(){
// flag 控制全选按钮是否选中
var flag = true;
// 循环检查按钮是否全部被选择
for (var j = 0; j < j_tbs.length; j++ ){
if (!j_tbs[j].checked){ // 如果有没有选中的
flag = false;
break;
}
}
j_cbAll.checked = flag; // 当为false时,会不勾选
}
}
</script>
</body>
</html>
4.7 自定义属性操作
4.7.1 获取属性值
element.属性
:获取属性值element.getAttribute("属性")
:获取属性值
<div class="cls"></div>
<script>
var div1 = document.querySelector("div");
console.log(div1.class);
console.log(div1.getAttribute("class"));
</script>
区别
element.属性
获取内置属性值(元素本身自带的属性)element.getAttribute("属性")
主要获得自定义的属性(标准)我们程序员自定义的属性
4.7.2 设置属性值
element.属性 = "值"
设置内置属性值element.setAttribute("属性", "值")
设置属性值
4.7.3 移除属性
element.removeAttribute("属性")
移除属性
4.8 H5自定义元素
自定义元素的目的:是为了保存并使用数据。有些数据可以保存到页面中二不用保存到数据库中
自定义属性获取是通过getAttribute("属性")
获取
但是有些自定义属性容易引起歧义,不容易判断是元素的内置属性还是自定义属性
H5 给我们新增了自定义属性
4.8.1 设置H5自定义属性
H5 规定自定义属性, data 开头作为属性名并且赋值
比如:
<div data-index="1"></div>
4.8.2 获取H5自定义属性
-
兼容性获取
element.getAttribute("属性名")
-
新增方法
element.dataset.属性
/element.dataset["属性名"]
var div1 = document.querySelector("div"); console.log(div1.dataset.index); console.log(div1.dataset["index"]); // dataset 是一个集合,里面存放了所有以data开头的自定义属性
5、 节点操作
5.1 为什么要学节点操作
获取元素通常使用两种方式
- 利用 DOM 提供的方法获取元素
- 逻辑性不强、繁琐
- 利用节点层级关系获取元素
- 利用父子兄弟节点关系获取元素
- 逻辑性强,但是兼容性较差
5.2 节点概述
网页中的所有内容都是节点(标签、属性、文本、注释等),在 DOM 中,节点使用 node 表示
HTML DOM 树中的所有节点均可以通过 JS 进行访问,所有 HTML 元素(节点)均可被修改,也可以创建或删除
一般的,节点至少拥有 nodeType(节点类型)、nodeName(节点名称)和 nodeValue(节点值)这三个基本属性
- 我们在实际开发中,节点操作的主要是元素节点
5.3 节点层级
利用 [DOM 树](#1.1 DOM树)可以把节点划分为不同层级关系,常见的是父子兄层级关系
5.3.1 父级节点
node.parentNode;
<div id="box">
<span class="erweima"></span>
</div>
<script>
var erweima = document.querySelector(".erweima");
var box = erweima.parentNode; // 得到父节点
</script>
得到的是离元素最近的父级节点
如果指定的节点没有父节点则返回 null
5.3.2 子节点
node.childNodes; // 标准
// 得到的是指定子节点的集合,该集合为及时更新的集合
node.firstChild; // 第一个子节点
node.lastChild; // 最后一个子节点
<body>
<ul>
<li>节点1</li>
<li>节点2</li>
<li>节点3</li>
<li>节点4</li>
<li>节点5</li>
</ul>
<script>
var ul = document.querySelector("ul");
var lis = ul.childNodes;
console.log(lis);
console.log(lis[0].nodeType);
console.log(lis[1].nodeType);
</script>
</body>
子节点,childNodes 所有的子节点,包含元素节点、文本节点等
如果只想获得里面的元素节点,则需要专门处理。所以我们一般不提倡使用 childNodes
var ul = document.querySelector("ul"); for (var i = 0; i < ul.childNodes.length; i++) { if (ul.child[i].nodeType == 1) { // 其为元素节点 console.log(ul.childNodes[i]); } }
node.children; // 非标准
// 其是一个只读属性,返回的子元素节点。它返回子元素节点,其余节点不返回
node.firstElementChild; // 第一个子元素节点
node.lastElementChild; // 最后一个子元素节点
// 找不到返回null
console.log(ul.children);
返回伪数组
5.3.3 兄弟节点
node.nextSibling;
// 返回当前元素的下一个兄弟节点,找不到返回null;其包含所有的节点
node.previousSibling;
// 返回当前元素的上一个元素的兄弟节点,找不到则返回null;同样,也是包含所有节点
node.nextElementSibling;
// 返回当前元素下一个兄弟元素节点,找不到返回null
node.previousElementSibling;
// 返回当前元素上一个兄弟元素节点,找不到返回null
5.4 创建节点
document.createElement("tagName"); // 创建节点
document.createElement()
方法创建由 tagName 指定的 HTML 元素。因为这些元素原先不存在,是根据我们的需求动态生成的,所以我们也称为动态创建元素节点
5.5 添加节点
node.appendChild(child);
node.appendChild() 方法将一个节点添加到指定父元素的子节点列表末尾。类似于 CSS 里面的 after 伪元素
<body>
<ul>
<li>1</li>
</ul>
<script>
// 创建节点
var li1 = document.createElement("li");
// 添加节点 node 父级 child 子级 后面追加元素
var ul = document.querySelector("ul");
ul.appendChild(li1);
</script>
</body>
node.insertBefore(child, 指定元素);
将一个节点添加到父节点的指定子节点前面,类似于 css 里面的 before 伪元素
5.6 发布留言案例
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
ul > li {
background-color: rgb(18, 143, 160); /* 背景颜色 */
margin-top: 10px; /* 外边距 */
list-style-type: none; /* 去除小圆点 */
color: red; /* 文本颜色 */
}
</style>
</head>
<body>
<textarea name="" id="" cols="30" rows="10"></textarea>
<button>发布</button>
<ul>
</ul>
<script>
var btn = document.querySelector("button"); // 获取按钮
var tara = document.querySelector("textarea"); // 获取输入框
var ul = document.querySelector("ul"); // 获取列表
btn.onclick = function() { // 注册事件
console.log(tara.value);
if (tara.value == "") { // 但输入框没有内容时
alert("请输入内容!")
} else {
var lin = document.createElement("li"); // 创建节点
lin.innerHTML = tara.value; // 修改内容
ul.insertBefore(lin, ul.children[0]); // 插入内容
tara.value = ""; // 清除文本框内容
}
}
</script>
</body>
</html>
5.7 删除节点
node.removeChild(child);
// 从 DOM 中删除一个子节点,返回删除
var btn = document.querySelector("button"); // 获取按钮
var ul = document.querySelector("ul"); // 获取列表
btn.onclick = function() { // 注册事件
if (ul.children.length === 0){
alert("里面没有内容!");
this.disabled = true; // 按钮被禁用
} else {
ul.removeChild(ul.children[(ul.children.length - 1)]);
console.log(ul.removeChild(ul.children[(ul.children.length - 1)])); // 返回被删除的内容
}
}
5.8 创建评论框
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
ul > li {
background-color: rgb(18, 143, 160); /* 背景颜色 */
margin-top: 10px; /* 外边距 */
list-style-type: none; /* 去除小圆点 */
color: red; /* 文本颜色 */
width: 300px;
}
li > a {
text-decoration: none;
color: black;
float: right;
font-size: 12px;
line-height: 20.8px;
}
</style>
</head>
<body>
<textarea name="" id="" cols="30" rows="10" placeholder="请输入评论"></textarea>
<button>发布评论</button>
<ul style="padding: 2px;">
</ul>
<script>
var btn = document.querySelector("button"); // 获取按钮
var tara = document.querySelector("textarea"); // 获取输入框
var ul = document.querySelector("ul"); // 获取列表
btn.onclick = function() { // 注册事件
if (tara.value == "") { // 但输入框没有内容时
alert("请输入内容!")
} else {
var lin = document.createElement("li"); // 创建节点
lin.innerHTML = tara.value + "<a href='javascript:;'>删除评论</a>"; // javascript:; 或者 javascript: void(0); 阻止链接跳转
ul.insertBefore(lin, ul.children[0]); // 插入内容
tara.value = ""; // 清除文本框内容
// 删除元素
var dul = document.querySelectorAll("a");
for (var i = 0; i < dul.length; i++) {
dul[i].onclick = function() {
ul.removeChild(this.parentNode); // 删除li标签
}
}
}
}
</script>
</body>
</html>
5.9 复制节点
node.cloneNode()
:复制节点
其返回调用该方法的一个副本,也称为克隆节点 / 拷贝节点
<body>
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
</ul>
<script>
var ul = document.querySelector("ul");
var li = ul.children[0].cloneNode(); // 只有标签,没有内容
var lc = ul.children[0].cloneNode(true); // 包括内容
ul.firstElementChild.appendChild(li);
ul.firstElementChild.appendChild(lc);
</script>
</body>
- 如果括号内参数为空或为 false,其为浅拷贝,即只克隆复制节点本身,不克隆里面的子节点
- 如果括号参数为 true,则是深度拷贝,会复制节点本身以及里面所有的子节点
5.10 动态生成表格
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
td > a {
text-decoration: none;
color: red;
}
table {
width: 500px;
margin: 100px auto;
border-collapse: collapse;
text-align: center;
}
td, th {
border: 1px solid #333;
}
thead tr {
height: 40px;
background-color: #ccc;
}
</style>
</head>
<body>
<table>
<thead>
<tr>
<th>姓名</th>
<th>科目</th>
<th>成绩</th>
<th>操作</th>
</tr>
</thead>
<tbody>
</tbody>
</table>
<script>
// 准备数据
var db = {
name: "李华",
subject: "JavaScript",
score: 100
}
var dbs = [
{
name: "李四",
subject: "JavaScript",
score: 20
}
]; // 存放数据
dbs[dbs.length] = db; // 添加数据
var tbody = document.querySelector("tbody");
for (var i = 0; i < dbs.length; i++) { // 向tbody里面添加数据
// 创建元素
var tr = document.createElement("tr");
tbody.appendChild(tr);
// 创建单元格--跟数据有关系的单元格
for (var j in dbs[i]) { // 遍历对象
var td = document.createElement("td");
tr.appendChild(td);
td.innerText = dbs[i][j]; // 属性值
}
// 创建有删除的单元格
var td = document.createElement("td");
tr.appendChild(td);
td.innerHTML = "<a href='javascript:;'> 删除 </a>";
}
// 注册删除事件
var as = tbody.querySelectorAll("a");
for (var i = 0; i < as.length; i++) {
as[i].onclick = function() {
// 点击删除,删除整行内容
tbody.removeChild(this.parentNode.parentNode);
}
}
</script>
</body>
</html>
5.11 三种动态创建元素的区别
-
document.write ( )
-
document.write("<div>123</div>");
-
在页面文档流加载完毕,直接将内容写入页面的内容流,则它会覆盖原来页面的内容
-
-
element.innerHTML
- 其是将内容写入某个 DOM 节点,不会导致页面全部重绘
- 其创建多个元素效率更高(使用数组形式拼接时),结构稍微复杂
-
document.createElement ( )
- 创建多个元素效率稍微低一点点,但是结构更清晰
6、 DOM 重点核心
文档对象模型,是 W3C 组织推荐的处理可扩展标记语言的标准编程接口
W3C 已经定义了一系列的 DOM 接口,通过这些 DOM 接口可以改变网页的内容、结构和样式
- 对于JS ,为了能够使 JS 操作 HTML ,JS 就有了一套自己的 DOM 接口
- 对于 HTML 来说,DOM 使得 HTML 形成一颗 DOM 树,包含文档、元素、节点
- 我们获取过来的 DOM 元素是一个对象,所以称为文档对象模型
关于 DOM 操作,我们主要针对元素的操作。主要有创建、删除、修改、查找、增加、事件操作
6.1 创建
document.write();
innnerHTML;
document.createElement();
6.2 增加
node.appendChild();
node.insertBefore();
6.3 删除
node.removeChild();
6.4 修改
主要修改 DOM 元素属性,DOM 元素的内容、属性,表单的值等
- 修改元素属性:src、href、title 等
- 修改普通元素内容;innerHTML、innerText
- 修改表单元素:value、type、disabled 等
- 修改元素样式:style、className、style.cssText 等
6.5 查找
主要获取查询 DOM 的元素
- DOM 提供 API 方法:getElementById、getElementsByTagName 等,古老用法不太推荐
- H5 提供的新方法:querySelector、querySelectorAll 推荐
- 利用节点操作获取元素:父(parentNode)、子(children)、兄(previousElementSibling / nextElementSiblling) 推荐
6.6 属性操作
主要针对自定义属性
- setAttribute:设置 DOM 的属性值
- getAttribute:得到 DOM 的属性值
- removeAttribute:移除属性
6.7 事件操作
给元素注册事件,采取事件源、事件类型 = 事件处理程序
7、 事件高级
7.1 注册事件
给元素添加事件,称为注册事件或者绑定事件
注册事件有两种方式:传统方式和方法监听注方式
7.1.1 传统注册
利用 on 开头的事件 onclick
-
<button onclick="alert('hello~')"></button>
-
btn.onclick = function() {}
-
特点
- 注册事件的唯一性
- 同一个元素同一个事件只能设置一个处理函数,最后注册的处理函数将会覆盖前面注册的函数
7.1.2 事件监听注册
W3C 标准推荐方式
addEventListener() // 是一个方法
// IE9 以前的IE不支持此方法,可使用 attachEvent() 代替
特点
- 同一个元素同一个事件可以注册多个监听器
7.1.2.1 addEventListener
eventTarget.addEventListener(type, listener [, useCapture]);
// 该方法将指定的监听器注册到 eventTarget 上,当该对象触发指定的事件时,就会执行事件处理函数
参数
- type:事件类型字符串,比如 click、mouseover 等,注意这里不要带 on
- listener:事件处理函数,事件发生时,会调用该监听函数
- useCapture:可选参数,是一个布尔值,默认是 false
<body>
<button id="eventLisetener">警告</button>
<script>
btn = document.getElementById("eventLisetener");
btn.addEventListener("click", function() { // 里面的事件类型是字符串,必定加引号,而且不带on
alert("hi~");
})
btn.addEventListener("click", function() { // 可以重复注册
alert("hello~");
})
</script>
</body>
7.1.2.2 attachEvent
eventTarget.attachEvent(eventNameWithOn, callback);
// 该方法将指定的监听器注册到 eventTarget 上,当该对象触发指定事件时,指定的回调函数就会执行
参数
- eventNameWithOn:事件类型字符串,比如 onclick、onmouseover 等,这里要带 on
- callback:事件处理函数,当目标触发事件时回调函数被调用
<body>
<button id="eventLisetener">警告</button>
<script>
btn = document.getElementById("eventLisetener");
btn.attachEvent("onclick", function() {
alert("我是老方法哦!") // IE9 版本以前的才支持
})
</script>
</body>
7.2 删除事件
7.2.1 传统事件
eventTarget.onclick = null;
// 传统绑定事件
// div[0].onclick = fn;
div[0].onclick = function() {
alert("传统方式注册事件");
div[0].onclick = null; // 删除事件
}
7.2.2 事件监听
7.2.2.1 removeEventListener
eventTarget.removeEventListener(type, listener [, useCapture]);
div[1].addEventListener("click", fn); // 里面的fn不需要调用加小括号
function fn() {
// 定义事件函数
alert("这是一个事件函数");
// 移除事件
div[1].removeEventListener("click", fn);
}
7.2.2.2 detachEvent
eventTarget.detachEvent(eventNameWithOn, callbackk);
div[2].attachEvent("onclick", fn);
function fn() {
alert("我是老方法哦!") // IE9 版本以前的才支持
// 移除事件
div[2].detachEvent("onclick", fn);
}
7.3 DOM 事件流
事件流描述的是从页面中接收事件的顺序
事件发生时会在元素节点之间按照特定的顺序传播,这个传播过程即 DOM 事件流
DOM 事件流分为三个阶段
- 事件捕获阶段
- 网景最早提出,由 DOM 最顶层节点开始,然后逐级向下传播到具体的元素接收的过程
- 当前目标阶段
- 事件冒泡阶段
- 事件冒泡:IE 最早提出,事件开始时由最具体的元素接收,然后逐级向上传播到 DOM 最顶层节点的过程
注意
-
JS 代码中只能执行捕获或者冒泡其中的一个阶段
-
传统事件和 attachEvent 只能的到冒泡阶段
-
addEventListener 第三个参数如果是 true ,表示在事件捕获阶段调用事件处理程序;如果是 false (默认为 false),表示在事件冒泡阶段调用事件处理程序
-
捕获阶段
-
<div class="father" style="width: 120px; height: 120px; background-color: blue;"> <div class="son" style="width: 100px; height: 100px; background-color: red;"></div> </div> <script> // 捕获阶段,如果 addEventListener 第三个参数是 true ,那么则处于捕获阶段 document -> html -> body -> father -> son var son = document.querySelector(".son"); son.addEventListener("click", function() { alert("son"); // 先执行 father 再 son }, true); son.parentElement.addEventListener("click", function() { alert("father"); }, true)
-
-
冒泡阶段
-
<div class="father" style="width: 120px; height: 120px; background-color: blue;"> <div class="son" style="width: 100px; height: 100px; background-color: red;"></div> </div> <script> // 冒泡阶段,如果 addEventListener 第三个参数是 false ,那么则处于冒泡阶段 son -> father -> body -> html -> document var son = document.querySelector(".son"); son.addEventListener("click", function() { alert("son"); // 先执行 son 再执行 father }); son.parentElement.addEventListener("click", function() { alert("father"); });
-
-
-
在实际开发中,我们很少使用事件捕获,我们更关注事件冒泡
-
有些事件是没有冒泡的,比如 onblur、onfocus、onmouseenter、onmouseleave
7.4 事件对象
<div style="border: 1px solid black; border-radius: 1px; width: 30px; height: 30px; background-color: aquamarine;">123</div>
<script>
var div = document.querySelector("div");
div.onclick = function(event) {
/*
1、 event 就是一个事件对象写到我们监听函数的小括号里面,当形参来看
2、 事件对象只有有了事件才会存在,它是系统自动创建的,不需要我们传递参数
3、 事件对象是我们事件的一系列相关数据的集合,跟事件相关的,比如鼠标点击事件里面就包括了鼠标的相关信息(鼠标坐标等),键盘事件里面就包含了键盘事件的信息(用户按下哪个键等)
4、 这个事件对象我们可以自己命名
5、 事件对象也有兼容性问题 ie9 通过 window.event,兼容性写法 event = event || window.event;
*/
console.log(event);
}
</script>
简单理解:事件发生后。跟事件相关的一系列信息数据集合都存放到这个对象里面,这个对象就是事件对象 event ,它有很多属性和方法
这个 event 是个形参,系统帮我们设定为事件对象,不需要传递实参过去
当我们注册事件时,event 对象就会被系统自动创建,并依次传递给事件监听器(事件处理函数)
7.4.1 事件对象的属性和方法
事件对象属性方法 | 说明 |
---|---|
event.target | 返回触发事件的对象(标准) |
event.srcElement | 放回触发事件的对象(非标) |
event.type | 返回事件的类型 |
event.cancelBubble | 该属性阻止冒泡的进行(非标) |
event.stopPropagation() | 阻止冒泡 (标准) |
event.returnValue | 该属性阻止默认事件(默认行为)(非标)比如不让链接跳转 |
event.preventDefault() | 该方法阻止默认事件(默认行为)(标准) |
7.4.1.1 target 和 this 的区别
<div>123</div>
<ul>
<li>abc</li>
<li>abc</li>
<li>abc</li>
</ul>
<script>
var div = document.querySelector("div");
var ul = document.querySelector("ul");
div.addEventListener("click", function(event) {
console.log(event.target);
console.log(this);
})
ul.addEventListener("click", function(event) {
console.log(event.target); // 返回点击的元素 li
console.log(this); // 返回 ul,this 指向 ul
})
</script>
target:点击了哪个元素,就返回哪个元素
this:哪个元素绑定了这个点击事件,那么久返回哪个元素
7.4.1.2 阻止冒泡
事件冒泡:开始时由最具体的元素接收,然后逐级向上传播到 DOM 最顶层节点
事件冒泡本身的特性,会带来坏处,也会有好处
阻止冒泡
-
标准写法:stopPropagation()
<div class="father" style="width: 120px; height: 120px; background-color: blue;"> <div class="son" style="width: 100px; height: 100px; background-color: red;"></div> </div> <script> var son = document.querySelector(".son"); son.addEventListener("click", function(event) { alert("son"); event.stopPropagation(); }); son.parentElement.addEventListener("click", function() { alert("father"); }); </script>
-
非标准写法:cancelBubble (IE9以下)
<div class="father" style="width: 120px; height: 120px; background-color: blue;"> <div class="son" style="width: 100px; height: 100px; background-color: red;"></div> </div> <script> var son = document.querySelector(".son"); son.addEventListener("click", function(event) { alert("son"); event.cancelBubble = true; // 停止冒泡 }); son.parentElement.addEventListener("click", function() { alert("father"); }); </script>
7.5 事件委托
事件委托也称为事件代理,在jQuery里面称为事件委派
原理
- 不是每个子节点单独设置事件监听器,而是事件监听器设置在其父节点上,然后利用冒泡原理影响设置每个子节点
作用
- 我们只操作了一次 DOM ,提高了程序执行的性能
<ul>
<li>234</li>
<li>234</li>
<li>234</li>
<li>234</li>
<li>234</li>
</ul>
<script>
// 事件委托
var ul = document.querySelector("ul");
ul.addEventListener("click", function(e) {
alert("hello~~~");
for (var i = 0; i < ul.children.length; i++) {
this.children[i].style.backgroundColor = "";
}
e.target.style.backgroundColor = "pink";
})
</script>
7.6 常用的鼠标事件
7.6.1 禁止选中
-
禁止鼠标右键
contextmenu 主要控制应该何时显示上下文菜单,主要用于程序员取消默认上下文菜单
document.addEventListener("contextmenu", function(e) { e.preventDefault(); // 阻止右键菜单 })
-
禁止鼠标选中
selectstart 开始选中
document.addEventListener("selectstart", function(e) { e.preventDefault(); // 阻止选中文字 })
7.6.2 鼠标事件对象
event 对象代表事件的状态,跟事件相关的一系列信息的集合
MouseEvent
和键盘事件对象 KeyboardEvent
鼠标事件对象 | 说明 |
---|---|
e.clientX | 返回鼠标相对于浏览器窗口可视区的X坐标 |
e.clientY | 返回鼠标相对于浏览器窗口可视区的Y坐标 |
e.pageX | 返回鼠标相对于页面文档的X坐标 IE9+支持 |
e.pageY | 返回鼠标相对于页面文档的Y坐标 IE9+支持 |
e.screenX | 返回鼠标相对于电脑屏幕的X坐标 |
e.screenY | 返回鼠标相对于电脑屏幕的Y坐标 |
7.7 常用的键盘事件
7.7.1 键盘事件
事件除了使用鼠标触发,还可以使用键盘触发
键盘事件 | 触发条件 |
---|---|
onkeyup | 某个键被松开时触发 |
onkeydown | 某个键被按下时触发 |
onkeypress | 某个键被按下时触发,但是它不识别功能键,如:Ctrl 等 |
document.addEventListener("keyup", function(e) {
console.log("我起飞了");
})
document.addEventListener("keydown", function() {
console.log("我落地了");
})
document.addEventListener("keypress", function() {
console.log("我又落地了");
})
三个事件的执行顺序:keydown -> keypress -> keyup
7.7.2 键盘事件对象
keyCode:返回该键的 ASCII 值
document.addEventListener("keyup", function(e) {
console.log(e);
console.log(e.keyCode); // 得到相应键的ASCII码值
/*
同时,我们的 keyup 和 keydown 事件不区分字母大小写,a 和 A 都为65
keypress事件区分字母大小写,a 为 97、A 为 65
*/
})
本文来自博客园,作者:Kenny_LZK,转载请注明原文链接:https://www.cnblogs.com/liuzhongkun/p/15886523.html