节点操作
删除节点
node.remobeChild(child)
node.removeChild()方法是从DOM中删除一个子节点,返回被删除的节点
<!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>
<ul>
<li>第一个孩子</li>
<li>第二个孩子</li>
<li>第三个节点</li>
<li>第四个孩子</li>
</ul>
<button>按钮</button>
<script>
// 获取元素
var ul = document.querySelector('ul');
var bth = document.querySelector('button');
bth.onclick = function() {
if (ul.children.length == 0) {
this.disabled = true
} else {
ul.removeChild(ul.children[0])
}
}
</script>
</body>
</html>
删除留言板功能
思路如下
- 给li赋值的时候多加一个链接
- 获取所有的链接,点击链接让链接所在的父元素消失
<!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>
textarea {
width: 600px;
height: 200px;
}
li {
list-style: none;
width: 600px;
background-color: #33cc33;
margin-top: 20px;
}
a {
float: right;
}
</style>
</head>
<body>
<textarea></textarea>
<button>留言</button>
<ul></ul>
<script>
// 获取元素
var text = document.querySelector('textarea');
var button = document.querySelector('button');
var ul = document.querySelector('ul');
button.onclick = function() {
if (text.value == "") {
alert('没有输入内容')
return false
} else {
var li = document.createElement("li");
li.innerHTML = text.value + "<a href='javasript:;'>删除</a>"
ul.insertBefore(li, ul.children[0])
// 获取所有的a
var as = document.querySelectorAll('a');
console.log(as)
for (var i = 0; i < as.length; i++) {
as[i].onclick = function() {
ul.removeChild(this.parentNode)
}
}
}
}
</script>
</body>
</html>
克隆节点
node.cloneNode():当参数为空或者false的情况下 即为浅拷贝,只复制结构不复制内容,当参数为true的时候,复制结构及内容
<!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>
* {
margin: 0;
padding: 0;
}
li {
width: 500px;
color: white;
font-weight: 700;
background-color: royalblue;
margin: 5px auto;
}
</style>
</head>
<body>
<ul>
<li>一</li>
<li>二</li>
<li>三</li>
<li>四</li>
<li>五</li>
</ul>
<script>
var ul = document.querySelector('ul');
var li = ul.children[0].cloneNode(true);
ul.insertBefore(li,ul.children[0])
</script>
</body>
</html>
动态创建表格
- 因为里面的学生是动态,我们需要JS生成表格,这里我们模拟数据,自己定义好数据,我们采用对象的方法存储y
- 所有的数据都是放在tbody里面的行里面。
- 因为行很多 我们需要创建多个行(对应多少人)
- 每个行里面又有很多单元格(对应里面的数据),我们还得继续使用循环创建多个单元格,并且把数据存入里面
- 最后一列单元格是删除,需要单独创建单元格
- 最后添加删除操作,点击删除,删除当前行
<!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>
* {
margin: 0;
padding: 0;
}
table {
width: 600px;
margin: 200px auto;
text-align: center;
border-collapse: collapse;
}
thead tr {
background-color: skyblue;
}
tr,
td,
th {
border: 1px solid black;
padding: 10px 0px;
}
</style>
</head>
<body>
<table>
<thead>
<tr>
<th>姓名</th>
<th>学科</th>
<th>成绩</th>
<th>操作</th>
</tr>
</thead>
<tbody>
</tbody>
</table>
<script>
// 创建对象
var dates = [{
name: '尧子陌',
subject: 'javascript',
score: "80"
}, {
name: '惊鸿',
subject: 'javascript',
score: "85"
}, {
name: '临风笑却世间',
subject: 'javascript',
score: "80"
}
]
// 获取元素
var tbody = document.querySelector('tbody');
for (var i = 0; i < dates.length; i++) {
var tr = document.createElement("tr");
tbody.appendChild(tr);
for (k in dates[i]) {
var td = document.createElement("td");
tr.appendChild(td);
td.innerHTML = dates[i][k]
}
// 生成删除按钮,需要单独进行循环
var td = document.createElement('td');
td.innerHTML = "<a href ='javascript:;'>删除</a>"
tr.appendChild(td)
}
var as = document.querySelectorAll('a');
console.log(as)
for (var i = 0; i < as.length; i++) {
as[i].onclick = function() {
tbody.removeChild(this.parentNode.parentNode)
}
}
</script>
</body>
</html>
创建动态元素三种方式
- document.write()
- element.innerHTML
- document.creatElement()
区别
- document.write是将页面直接写入内容,但是文档流执行完毕后,会导致页面内容全部重绘
- innerHTML是将内容写入DOM节点,不会导致页面的重绘
- innerHTML创建多个元素效率更高(不要拼接字符串,采用数组方式拼接),结构稍微复杂
- creatElement()创建多个元素效率稍低一点点,但是结构更清晰
总结 :不同浏览器下,innerHTML效率要比creatElement高
document.write()
<!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>
<button>按钮</button>
</body>
<script>
// 获取元素
var bth = document.querySelector('button');
bth.onclick = function() {
document.write("hello")
}
</script>
</html>
innerHTML()
<!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>
<div class="inner"></div>
</body>
<script>
var inner = document.querySelector('.inner');
// 1.不推荐使用
// for (var i = 0; i < 10; i++) {
// inner.innerHTML += "<b>innerHTML</b>"
// }
// 2.推荐使用
var arr = [];
for (var i = 0; i < 10; i++) {
arr.push('<b>innerHTML</b>')
};
inner.innerHTML = arr.join('')
</script>
</html>
creatElement()
<!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>
textarea {
width: 600px;
height: 200px;
}
li {
list-style: none;
width: 600px;
background-color: #33cc33;
margin-top: 20px;
}
a {
float: right;
}
</style>
</head>
<body>
<textarea></textarea>
<button>留言</button>
<ul></ul>
<script>
// 获取元素
var text = document.querySelector('textarea');
var button = document.querySelector('button');
var ul = document.querySelector('ul');
button.onclick = function() {
if (text.value == "") {
alert('没有输入内容')
return false
} else {
var li = document.createElement("li");
li.innerHTML = text.value + "<a href='javasript:;'>删除</a>"
ul.insertBefore(li, ul.children[0])
// 获取所有的a
var as = document.querySelectorAll('a');
console.log(as)
for (var i = 0; i < as.length; i++) {
as[i].onclick = function() {
ul.removeChild(this.parentNode)
}
}
}
}
</script>
</body>
</html>
innerHTML的执行效率
<!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>
* {
margin: 0;
padding: 0;
}
div {
width: 120px;
height: 10px;
margin: 10px;
border: 1px solid black;
}
</style>
</head>
<body>
</body>
<script>
function getTime() {
var d1 = +new Date();
for (var i = 0; i < 1000; i++) {
document.body.innerHTML += '<div></div>';
}
var d2 = +new Date();
console.log(d2 - d1);
}
getTime()
</script>
</html>
innerHTML数组的执行效率
<!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>
div {
width: 120px;
height: 4px;
border: 1px solid red;
margin: 5px;
}
</style>
</head>
<body>
</body>
<script>
function getTime() {
var t1 = Date.now();
var arr = [];
for (var i = 0; i < 1000; i++) {
arr.push('<div></div>')
}
document.body.innerHTML = arr.join('')
var t2 = +new Date();
console.log(t2 - t1)
}
getTime()
</script>
</html>
creatElement()的执行效率
<!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>
div {
width: 120px;
height: 4px;
border: 1px solid red;
margin: 5px;
}
</style>
</head>
<body>
</body>
<script>
function getTime() {
var t1 = Date.now();
for (var i = 0; i < 1000; i++) {
var div = document.createElement('div')
document.body.appendChild(div)
}
var t2 = +new Date();
console.log(t2 - t1)
}
getTime()
</script>
</html>
DOM核心总结
> DOM:文档对象模型。主要提供访问与操作网页内容的接口与方法.DOM主要对元素进行操作。主要有创建、增、删、改、查、属性操作、事件操作
创建
增加元素
删除元素
更改元素
属性操作
事件操作
事件
监听方式
给元素添加事件 称为注册事件
监听方式分为两种:传统监听方式 事件监听方式
区别如下
addEventListener()事件监听(IE9以后支持)
- type:事件类型字符串,如onclick onmouseover等等
- listener:事件处理函数,事件发生时,调用该监听函数
- useCapture:可选函数,是一个布尔值,默认值是false
attacheEvent()事件监听(IE678支持)
事件监听解决方案
解绑事件
传统注册方式
eventTarget.onclick = null;
事件监听注册方式
eventTarget.removeEventListener(type,listener[,useCapture]);
eventTarget.detachEvent(eventNameWithOn,callback)
<!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>
* {
margin: 0;
padding: 0;
}
div {
width: 200px;
height: 200px;
background-color: blue;
margin: 5px;
}
</style>
</head>
<body>
<div></div>
<div></div>
<div></div>
<script>
var divs = document.getElementsByTagName('div');
divs[0].onclick = function() {
alert('1');
divs[0].onclick = null;
}
divs[1].addEventListener('click', fn);
function fn() {
alert('2');
divs[1].removeEventListener('click', fn)
}
divs[2].attachEvent('onclick', fn1);
function fn1() {
alert(3);
divs[2].detachEvent('onclick', fn1);
}
</script>
</body>
</html>
DOM事件流
> 事件发生时,会在元素节点之间按照特定的顺序传播,这个传播过程即DOM事件流。
注意
- js代码只能执行捕获和冒泡的其中一个阶段
- onclick和attachEvent只能达到冒泡阶段
- addEventListener(type,listener[,useCapture])第三个参数是true,表示进入事件捕获阶段,如果是false,表示事件进入冒泡阶段
- 实际开发的过程中,我们很少使用事件捕获,我们更关注事件冒泡。
- 有些事情是没有冒泡的,如onblur,onfocus,onmouseenter等等
捕获阶段
<!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>
.father {
overflow: hidden;
width: 800px;
height: 800px;
margin: 200px auto;
background-color: blue;
}
.son {
width: 400px;
height: 400px;
margin: 200px;
background-color: yellow;
}
</style>
</head>
<body>
<div class="father">
<div class="son"></div>
</div>
<script>
// 获取元素
var father = document.querySelector('.father');
var son = document.querySelector('.son');
father.addEventListener('click', function() {
alert('father')
}, true)
son.addEventListener('click', function() {
alert('son')
}, true)
</script>
</body>
</html>
冒泡阶段
<!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>
.father {
overflow: hidden;
width: 800px;
height: 800px;
margin: 200px auto;
background-color: blue;
}
.son {
width: 400px;
height: 400px;
margin: 200px;
background-color: yellow;
}
</style>
</head>
<body>
<div class="father">
<div class="son"></div>
</div>
<script>
// 获取元素
var father = document.querySelector('.father');
var son = document.querySelector('.son');
father.addEventListener('click', function() {
alert('father')
}, false)
son.addEventListener('click', function() {
alert('son')
}, false)
</script>
</body>
</html>
通过两个案例不难发现,捕获事件是从上往下依次执行,冒泡事件是从下往下依次执行
事件对象
- 事件对象写在侦听函数后面的小括号,当形参使用。是系统自动创建的,不需要传递任何的参数
- 事件对象是关于事件的相关数据的集合。
- 事件对象的名字可以被我们命名的,如e event evt等等
- 事件对象也有兼容性问题,在IE下通过window.event才能识别。
事件对象的兼容性写法
<!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>
* {
margin: 0;
padding: 0;
}
button {
display: block;
width: 200px;
height: 200px;
margin: 200px auto;
}
</style>
</head>
<body>
<button>按钮</button>
<script>
//获取元素
var bth = document.querySelector('button');
bth.onclick = function(e) {
e = e || window.event;
console.log(e)
}
</script>
</body>
</html>
事件对象的常见的属性与方法
e.target
区别如下
- this是指绑定的事件对象
- e.etarget是指被触发的事件对象
<!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>
* {
margin: 0;
padding: 0;
}
button {
margin-bottom: 20px;
}
ul {
list-style: none;
width: 200px;
border: 1px solid red;
}
li {
width: 200px;
height: 100px;
background-color: pink;
margin-bottom: 5px;
}
</style>
</head>
<body>
<button>按钮</button>
<ul>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
</ul>
<script>
var bth = document.querySelector('button');
var ul = document.querySelector('ul')
bth.addEventListener('click', function(e) {
console.log(e.target);
console.log(this)
})
ul.addEventListener('click', function(e) {
console.log(e.target);
console.log(this)
})
</script>
</body>
</html>
e.target与e.srcElement的兼容性写法
<!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>
* {
margin: 0;
padding: 0;
}
button {
display: block;
width: 200px;
height: 100px;
margin: 20px auto;
}
</style>
</head>
<body>
<button>按钮</button>
<script>
var bth = document.querySelector('button');
bth.onclick = function(e) {
e = e || window.event;
var target = e.target || e.srcElement;
console.log(target)
}
</script>
</body>
</html>
e.type返回事件的类型
<!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>
* {
margin: 0;
padding: 0;
}
button {
display: block;
width: 50px;
height: 50px;
margin: 200px auto;
}
</style>
</head>
<body>
<button>按钮</button>
<script>
var bth = document.querySelector("button");
bth.onclick = function(e) {
console.log(e.type)
}
</script>
</body>
</html>
e.returnValue e.preventDefault() 阻止默认行为
<!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>
* {
margin: 0;
padding: 0;
}
a {
display: block;
width: 50px;
height: 50px;
color: white;
margin: 200px auto;
text-align: center;
text-decoration: none;
line-height: 50px;
background: pink;
}
</style>
</head>
<body>
<a href="https://www.baidu.com/">百度</a>
<script>
var a = document.querySelector('a');
a.onclick = function(e) {
e.preventDefault();
e.returnValue;
}
</script>
</body>
</html>
阻止事件冒泡
- e.stopPropagation()
- e.cancelBubble = true
<!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>
.father {
overflow: hidden;
width: 800px;
height: 800px;
margin: 200px auto;
background-color: blue;
}
.son {
width: 400px;
height: 400px;
margin: 200px;
background-color: yellow;
}
</style>
</head>
<body>
<div class="father">
<div class="son"></div>
</div>
<script>
// 获取元素
var father = document.querySelector('.father');
var son = document.querySelector('.son');
father.addEventListener('click', function(e) {
alert('father');
}, false)
son.addEventListener('click', function(e) {
alert('son')
e.stopPropagation()
e.cancelBubble = true
}, false)
</script>
</body>
</html>
事件委托
给父节点添加侦听器 利用事件冒泡影响每个子节点
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
<ul>
<li>知否</li>
<li>知否</li>
<li>知否</li>
<li>知否</li>
<li>知否</li>
<li>知否</li>
</ul>
<script>
var ul = document.querySelector("ul");
var lis = document.querySelectorAll('li')
ul.addEventListener('click',function(e){
e.target.style.backgroundColor='purple'
})
</script>
</body>
</html>
常见鼠标事件
禁止右键和禁止复制文字
contextmenu :禁止右键
selectstart :禁止复制文字
<!DOCTYPE html>
<html lang="zh">
<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></title>
</head>
<body>
大家好 我的名字叫尧子陌 很高兴认识大家哦
</body>
<script>
// 禁用右键菜单
document.addEventListener('contextmenu',function(e){
e.preventDefault()
})
// 禁用复制文字
document.addEventListener('selectstart',function(e){
e.preventDefault()
})
</script>
</html>
鼠标事件对象
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
<script>
document.addEventListener('click',function(e){
console.log(e);
// 鼠标距离可视区的x和y坐标
console.log(e.clientX);
console.log(e.clientY);
// 鼠标距离文档的x和y坐标
console.log(e.pageX);
console.log(e.pageY);
// 鼠标距离屏幕的X坐标和Y坐标
console.log(e.screenX);
console.log(e.screenY);
})
</script>
</body>
</html>
小天使案例
分析如下
1.鼠标不断的移动,使用鼠标移动事件:mousemove
2.在页面中移动,给document注册事件
3.图标要移动距离,而且不占位置,我们要使用绝对定位
4.核心原理:每次鼠标移动,都会获得新的鼠标坐标,把这个x和y坐标作为图片的top和left值就可以移动图片。
<!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>
img {
position: absolute;
top: 2px;
}
</style>
</head>
<body>
<img src="images/angel.gif" alt="">
<script>
var pic = document.querySelector('img');
document.addEventListener('mousemove', function(e) {
// 1. mousemove只要我们鼠标移动1px 就会触发这个事件
// console.log(1);
// 2.核心原理: 每次鼠标移动,我们都会获得最新的鼠标坐标, 把这个x和y坐标做为图片的top和left 值就可以移动图片
var x = e.pageX;
var y = e.pageY;
console.log('x坐标是' + x, 'y坐标是' + y);
//3 . 千万不要忘记给left 和top 添加px 单位
pic.style.left = x - 50 + 'px';
pic.style.top = y - 40 + 'px';
});
</script>
</body>
</html>
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。