一、节点操作
1.删除节点
node.removeChild(); 方法从node节点中删除一个子节点,返回删除的节点
javascript
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>01删除节点</title>
</head>
<body>
<button id="btn">删除</button>
<ul id="ul">
<li>光头强</li>
<li>熊大</li>
<li>熊二</li>
</ul>
<script>
//1.获取元素
var ul = document.getElementById('ul');
var btn = document.getElementById('btn');
//2.注册事件
btn.onclick = function(){
if(ul.children.length == 0){
this.disabled = true; //按钮禁用
} else {
//node.removeChild(要删除的对象);
//ul.children[下标]表示是第几个孩子
ul.removeChild(ul.children[0]);
}
}
</script>
</body>
</html>
2.删除留言案例
javascript
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>02删除留言案例</title>
<style>
*{margin: 0; padding: 0;}
body{padding: 100px;}
textarea{
width: 200px;
height: 100px;
border: 1px solid red;
resize: none;
}
ul {
margin-top: 50px;
}
li{
width: 300px;
padding: 5px;
background-color: pink;
color: #fff;
font-size: 14px;
margin: 15px 0;
}
</style>
</head>
<body>
<textarea name="" id="text"></textarea>
<br/>
<button id="btn">发布</button>
<ul id="ul">
</ul>
<script>
//1.获取元素
var btn = document.getElementById('btn');
var text = btn.previousElementSibling.previousElementSibling;//上一个兄弟节点
var ul = btn.nextElementSibling; //获取下一个兄弟节点
//2.注册事件
btn.onclick = function(){
if(text.value == ''){
alert('请输入内容');
return false;
} else {
//2.1 创建元素
var li = document.createElement('li');
//2.2 给li里面添加内容
li.innerHTML = text.value + "<a href='javaScript:void(0);' class='rm'>删除</a>";
//2.3 添加元素
//ul.appendChild(li);
ul.insertBefore(li,ul.children[0]); //添加ul前面的第一个位置
//2.4 获取到所有的a标签对象
var as = document.getElementsByClassName('rm');
//2.5 遍历所有的a,并给他注册事件
for(var i = 0; i < as.length; i++){
as[i].onclick = function(){
//删除当前点击的这个节点
//this是a标签对象 this.parentNode表示当前点击的这个li的父亲
ul.removeChild(this.parentNode);
}
}
}
}
</script>
</body>
</html>
3.复制(克隆)节点
node.cloneNode(); 括号里面可以不写,默认值是false,表示是浅拷贝,只拷贝标签不拷贝内容
node.cloneNode(true); 表示深拷贝,会拷贝标签和里面的内容
javascript
<!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 id="ul">
<li>111</li>
<li>222</li>
<li>333</li>
</ul>
<script>
// 1.获取对象
var ul = document.getElementById('ul');
//2 - 1 node.cloneNode();括号为空或者里面的值是false,表示浅拷贝,只复制标签不只复制里面的内容
var li1 = ul.children[0].cloneNode();
//2 - 2 node.cloneNode(true);括号为true,表示深拷贝,复制标签并且会复制标签种的内容
var li2 = ul.children[0].cloneNode(true);
//3.添加到ul中
ul.appendChild(li1);
ul.appendChild(li2);
</script>
</body>
</html>
案例------动态生成表格
javascript
<!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{
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 id="tbody">
</tbody>
</table>
<script>
//准备table中要添加的数据
var datas = [
{
name:'柯震东',
subject:'JavaScript',
score:100
},
{
name:'房祖名',
subject:'Java',
score:90
},
{
name:'蔡徐坤',
subject:'Python',
score:80
}
];
//往tbody种创建行
var tbody = document.getElementById('tbody');
//有多少条数据,添加多少次
for(var i = 0; i < datas.length; i++){
//1.创建tr行
var tr = document.createElement('tr');
//2.创建td (td的创建熟练和datas中的属性的个数有关)
for(var k in datas[i]){ //循环datas中的属性
var td = document.createElement('td');
//把对象里面的属性值data[i][k]给td
//3.td中添加数据
//console.log(k + '--->' + datas[i][k]);
td.innerHTML = datas[i][k]; //给属性赋值
//4.将td加入到tr
tr.appendChild(td);
}
//添加操作按钮
var td = document.createElement('td');
td.innerHTML = '<a href="javaScript:;" class="del">删除</a>'
tr.appendChild(td);
//5.再将tr加入到tbody里面去
tbody.appendChild(tr);
}
//删除操作
//1.获取到所有的删除按钮
var as = document.getElementsByClassName('del');
//2.循环遍历,注册事件
for(var i = 0; i < as.length; i++){
as[i].onclick = function(){
tbody.removeChild(this.parentNode.parentNode);
}
}
</script>
</body>
</html>
4.创建元素的三种方式
- document.write();
- element.innerHTML
- document.createElement();
区别:
- document.write(); 是直接将内容写入到也买你内容流,但是文档流执行完毕,则它会导致页面全部重绘
- innerHTML 是将内容写入到某个DOM节点,不会导致整个页面重绘,创建多个元素效率更高(不要拼接字符串,采取数组形式拼接),结构稍微复杂
- createElement() 创建多个元素效率低一点点,但是结构更清晰(推荐)
**注意:**innerHTML效率要比createElement高
4.1 创建方式
javascript
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>05三种创建元素的方式</title>
</head>
<body>
<button id="btn">点击</button>
<p>abc</p>
<div id="inner"></div>
<div id="create"></div>
<script>
var btn = document.getElementById('btn');
//1.document.write(); 创建元素,因为会重绘整个页面,很多场合不太适用
// btn.onclick = function(){
// document.write('<div>123<div>');
// }
//2.innerHTML创建元素
var inner = document.getElementById('inner');
// for(var i = 0; i <= 100; i++){
// inner.innerHTML += '<a href="#">百度</a>'
// }
var arr = [];
for(var i = 0 ;i <= 100; i++){
arr.push('<a href="#">百度</a>');
}
inner.innerHTML = arr.join('');
//3.document.createElement()创建元素
var create = document.getElementById('create');
for(var i = 0; i <= 100; i++){
var a = document.createElement('a');
a.setAttribute('href','#');
a.innerHTML = '百度'
create.append(a);
}
</script>
</body>
</html>
4.2 效率对比
innerHTML字符串拼接方式---效率低
createElement效率一般
innerHTML数组方式--效率高
innerHTML拼接字符串效率最低
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>06效率测试-innerHTML字符串拼接</title>
</head>
<body>
<script>
function fn(){
var d1 = + new Date();
var str = '';
for(var i = 0; i < 1000; i++){
document.body.innerHTML += '<div style="width:100px;height=2px;border:1px solid blue;"></div>'
}
var d2 = + new Date();
console.log(d2 - d1);
}
fn();
</script>
</body>
</html>
innerHTML拼接数组效率最高
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>07效率测试-innerHTML数组拼接</title>
</head>
<body>
<script>
function fn(){
var d1 = + new Date();
var arr = [];
for(var i = 0; i < 1000; i++){
arr.push('<div style="width:100px;height=2px;border:1px solid blue;"></div>')
}
document.body.innerHTML = arr.join('');
var d2 = + new Date();
console.log(d2 - d1);
}
fn();
</script>
</body>
</html>
createElement效率一般
javascript
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>06效率测试-innerHTML字符串拼接</title>
</head>
<body>
<script>
function fn(){
var d1 = + new Date();
for(var i = 0; i < 1000; i++){
//document.body.innerHTML += '<div style="width:100px;height=2px;border:1px solid blue;"></div>'
var div = document.createElement('div');
div.style.width = '100px';
div.style.height = '2px';
div.style.border = '1px solid blue'
document.body.appendChild(div);
}
var d2 = + new Date();
console.log(d2 - d1);
}
fn();
</script>
</body>
</html>
5.DOM核心总结
5.1 节点API
对于javaScript来说,为了操作HTML,js就有了一套自己的DOM编程接口
- 创建节点
- document.write()
- innerHTML
- createElement
- 增加(将节点添加到某个节点)
- appendChild
- insertBefore
- 删除
- removeChild
- 改
- 修改内容:innerHTML,innerText
- 修改表单元素:value、type、disabled等等
- 修改元素样式:style、className
- 查询
- 主要查找dom的元素怒
- DOM提供的API方法:document.getElementById(id)、document.getElementsByTagName、document.getElementsByClassName
- H5提供了新方法:querySelector、querySelectorAll
- 利用节点操作获取元素:父节点(parentNode)、子节点(children)、兄(previousElementSibling、nextElementSibling)
5.2 属性操作
自定义属性
- setAttribute 设置dom的属性值
- getAttribute 获取dom的属性值
- removeAttribute 移除属性值
内置属性:对象.属性=值; 对象.属性 获取值
5.3 事件操作(重点)
二、高级事件
1.注册事件
注册事件有两种方式:
- 传统方式
- 利用on开头的事件,如:onclick
- 特点:注册事件的唯一性。同一个元素同一个事件只能设置一个处理函数,最后注册的处理函数将会覆盖前面注册的处理函数。
- 监听注册方式
- w3c标准推荐方式
- addEventListener() 它是一个方法。
- 特点:同一个元素同一个事件可以注册多个监听器,执行顺序按照注册顺序依次执行。
2.事件监听
javascript
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>09事件监听</title>
</head>
<body>
<button id="btn1">传统注册事件</button>
<button id="btn2">方法监听注册事件</button>
<script>
//获取到按钮
var btn1 = document.getElementById('btn1');
var btn2 = document.getElementById('btn2');
//1.传统注册事件
btn1.onclick = function(){
alert('this is btn1');
}
btn1.onclick = function(){
alert('btn1 hahahahahaahahah');
}
//2.事件监听 addEvenetListener
// 1)里面的事件类型是一个字符串,必须加引号而且不带on
// 2)同一个元素,同一个事件可以添加多个监听
btn2.addEventListener('click',function(){
alert('this is btn2');
});
btn2.addEventListener('click',function(){
alert('btn2~~~~~~~~~~~~');
});
//3.【了解】 attachEvent ie9以前的版本支持
// btn1.attachEven('onclick',function(){
// alert('1111111');
// });
</script>
</body>
</html>
3.删除事件(解绑事件)
removeEventListener 删除事件
javascript
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>10删除事件</title>
<style>
div{
width: 100px;
height: 100px;
background-color: pink;
}
</style>
</head>
<body>
<div>1</div>
<div>2</div>
<div>3</div>
<script>
//获取所有的div
var divs = document.querySelectorAll('div');
// var divs = document.getElementsByTagName('div');
//给第一个div注册事件
divs[0].onclick = function(){
alert(111111);
//传统的方式删除事件
divs[0].onclick = null;
}
//removeEventListener 删除事件
divs[1].addEventListener('click',fn);
function fn(){
alert(2222222);
//删除事件
divs[1].removeEventListener('click',fn);
}
</script>
</body>
</html>
4.DOM事件流
html中的标签都是相互嵌套的,我们可以将元素想象成一个盒子装着另一个盒子,document就是最外面的大盒子
当你单击一个div的时候,同时你页单击了div的父元素,甚至是整个页面
那么是先执行父元素的单击事件,还是先执行里面的div单击事件?
事件流描述的是从页面中接受事件的顺序
事件发生的时候在元素节点直接按照特点的顺序传播,这个传播过程,我们就称之为DOM事件流
- 事件冒泡:IE浏览器最早提出,事件开始时由最具体的元素接受,然后逐级向上传播到DOM最顶层节点过程
- 事件捕获:网景最早提出,由DOM最顶层节点开始,然后逐层向下传播到最具体的元素接受的过程。
text
当时这2大浏览器霸主谁也不服谁。
IE提出从目标元素开始,然后一层一层向外接受事件并响应,也就是冒泡型事件流。
网景提出从最外层开始,然后一层一层向内接受事件并响应,也就是事件捕获流
最终,w3c采用折中的方式,先捕获再冒泡
现代浏览器都遵循了此标准,所以事件发生的时候,会经历三个阶段。
- 1.捕获阶段
- 2.当前目标阶段
- 3.冒泡阶段
javascript
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>11.事件的三个阶段</title>
<style>
#father{
width: 300px;
height: 300px;
margin: 100px auto;
background-color: pink;
text-align: center;
}
#son{
width: 200px;
height: 200px;
margin: 50px;
background-color: purple;
line-height: 200px;
color: #fff;
}
</style>
</head>
<body>
<div id="father">
<div id="son">son盒子</div>
</div>
<script>
//dom事件流三个阶段:
//1.js代码中只能执行捕获或冒泡其中的一个阶段
//2.onclick只能得到冒泡阶段
//3.捕获阶段,如果addEvenetListner 第三个参数是true,那么则处于捕获阶段 document->html->body->father->son
// var son = document.getElementById('son');
// son.addEventListener('click',function(){
// alert('son');
// },true)
// var father = document.getElementById('father');
// father.addEventListener('click',function(){
// alert('father');
// },true)
//4.冒泡阶段,如果addEvenetListner第三个参数是false 或者省略不写,则处于冒泡阶段
var son = document.getElementById('son');
son.addEventListener('click',function(){
alert('son');
},false)
var father = document.getElementById('father');
father.addEventListener('click',function(){
alert('father');
},false)
document.addEventListener('click',function(){
alert('document');
})
</script>
</body>
</html>
5.事件对象
5.1 什么是事件对象
事件发生后,跟事件相关的一系列信息数据的集合都放在这个对象里面,这个对象就是事件对象。
如:
- 谁绑定了事件
- 鼠标触发事件的话,会得到鼠标相关的信息,如:鼠标的位置
- 键盘触发事件的话,会得到键盘相关的信息,如:按下了哪个键
5.2 事件对象使用
div.onclick = function(e){}
div.addEventListener('click',function(event){
console.log(event);
});
javascript
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>12事件对象</title>
<style>
div{
width: 100px;
height: 100px;
background-color: pink;
}
</style>
</head>
<body>
<div>123</div>
<script>
//事件对象
var div = document.querySelector('div');
// div.onclick = function(e){
// // console.log(e);
// // console.log(window.event);
// e = e || window.event;
// console.log(e);
// }
div.addEventListener('click',function(event){
console.log(event);
});
//1.event:就是一个事件对象,写到我们侦听函数的小括号里,当作形参来看
//2.事件对象只有有了事件才会存在,它是系统给我们自动创建的,不需要我们传递参数
//3.事件对象是我们事件的一些列相关数据的集合,跟事件相关,比如事件点击里面就包含了鼠标的相关信息
// 鼠标的坐标,比如是键盘事件里面会包含键盘事件信息,比如判断用户按下了哪个键
//4.这个事件我们可以自己命名的,比如:event、evt、e
//5.事件对象也有兼容性的问题,现在没有问题了,有兼容性问题(IE678版本)可以写成e = e || window.event;
</script>
</body>
</html>
5.3 e.target和this的区别
- this是使劲按绑定的元素(绑定这个事件处理函数的元素)
- e.target是事件触发的元素
通常情况下target和this是一致的。
但有一种情况不同:那就是再事件冒泡的时候。this指向的是父元素,而target指向的是子元素
this指向父元素是因为:它绑定的事件的元素对象就是父元素
target他是触发事件的哪个具体元素对象
javascript
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>13事件对象e.target</title>
</head>
<body>
<button id="btn">按钮</button>
<ul id="ul">
<li>abc</li>
<li>def</li>
</ul>
<script>
//常见事件的属性和方法
//1.e.target返回的是触发事件的对象(元素) this返回的是绑定事件的对象(元素)
//区别:e.target点击了哪个元素,就返回这个元素。 this那个元素绑定了这个点击事件,那么返回的就是绑定者
var btn = document.getElementById('btn');
btn.addEventListener('click',function(e){
console.log(e.target)
console.log(this);
});
var ul = document.getElementById('ul');
ul.addEventListener('click',function(e){
//因为我们给ul绑定了事件,那么this就是指向ul
console.log(this);
//console.log(e.currentTarget);
//e.target指向我们点击那个对象,谁触发了这个事件,那么e.target就是谁
console.log(e.target);
})
</script>
</body>
</html>
6.阻止默认行为
html中一些标签由默认行为,例如:a标签被点击了,默认进行页面跳转
javascript
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>14事件阻止默认行为</title>
</head>
<body>
<div>123</div>
<a href="http://www.baidu.com">百度</a>
<form action="http://www.baidu.com">
<input type="submit" value="提交">
</form>
<script>
//获取对象
var div = document.querySelector('div');
div.addEventListener('click',fn);
div.addEventListener('mouseover',fn);
div.addEventListener('mouseout',fn);
function fn(e){
console.log(e.type);
}
//2.阻止默认事件(行为),让超链接不跳转,或者是表单不提交
var a = document.querySelector('a');
// a.addEventListener('click',function(e){
// e.preventDefault(); //阻止默认 dom标准写法
// })
//3.传统注册方式
a.onclick = function(e){
//e.preventDefault();
return false; //利用return false也能阻止默认行为
}
var form = document.querySelector('form');
form.onsubmit = function(){
return false;
}
</script>
</body>
</html>
7.阻止事件冒泡
//阻止冒泡:dom推荐的是e.stopPropagation();
e.cancelBubble = true; //cancle:取消 Bubble:气泡,泡沫。(非标准写法)
javascript
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>15阻止事件冒泡</title>
<style>
.father{
width: 300px;
height: 300px;
margin: 100px auto;
background-color: pink;
text-align: center;
}
.son{
width: 100px;
height: 100px;
line-height: 100px;
margin: 100px;
background-color: purple;
color: #fff;
}
</style>
</head>
<body>
<div class="father">
<div class="son">son儿子</div>
</div>
<script>
//获取对象
//阻止冒泡:dom推荐的是e.stopPropagation();
var son = document.querySelector('.son');
var father = document.querySelector('.father');
son.addEventListener('click',function(e){
alert('son');
e.stopPropagation(); //阻止冒泡(传播) stop:阻止 Propagation:传播
},false);
father.addEventListener('click',function(e){
alert('father');
//e.stopPropagation();
e.cancelBubble = true; //cancle:取消 Bubble:气泡,泡沫。(非标准写法)
},false);
document.addEventListener('click',function(){
alert('document');
})
</script>
</body>
</html>
8.事件委托
事件冒泡本身的特性,会带来坏处,同时也会带来好处。
8.1 什么是事件委托
把事情委托给别人,代为处理
事件委托也称为事件代理,在jQuery里面称之为事件委派
大白话:不给子元素注册事件,给父元素注册事件,把处理代码在父元素的事件中执行。
8.2 应用案例
javascript
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>16.事件委托.html</title>
</head>
<body>
<ul>
<li>我爱中国1</li>
<li>我爱中国2</li>
<li>我爱中国3</li>
<li>我爱中国4</li>
<li>我爱中国5</li>
</ul>
<script>
//获取对象
var ul = document.querySelector('ul');
ul.addEventListener('click',function(e){
console.log(e.target);
e.target.style.backgroundColor = 'pink'
});
</script>
</body>
</html>
9.常见的鼠标事件
9.1 常见事件
鼠标事件 | 触发条件 |
---|---|
onclick |
鼠标点击左键触发 |
onmouseover |
鼠标经过触发 |
onmouseout |
鼠标离开触发 |
onfocus |
获取鼠标焦点 |
onblur |
失去鼠标焦点触发 |
onmousemove |
鼠标移动触发 |
onmouseup |
鼠标按键弹起触发 |
onmousedown |
鼠标按键按下触发 |
9.2 不可分享
javascript
<!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>我是一段小说文字</div>
<script>
// 1.contextmenu :就是我们鼠标右键事件
document.addEventListener('contextmenu',function(e){
e.preventDefault();
});
// 2.进制选中文字 selectstart
document.addEventListener('selectstart',function(e){
e.preventDefault()
})
</script>
</body>
</html>
9.3 鼠标事件对象
event 事件对象是事件相关的一系列信息的集合
现阶段我们主要使用鼠标事件对MouseEvent 和 键盘事件对象 KeyboardEvent
鼠标事件对象 | 说明 |
---|---|
e.clientX |
返回鼠标相对于浏览器窗口可视区域的X坐标 |
e.clientY |
返回鼠标相对于浏览器窗口可视区域的Y坐标 |
e.pageX |
IE9+支持,返回鼠标相对于文档页面X坐标 |
e.pageY |
IE9+支持,返回鼠标相对于文档页面Y坐标 |
e.screenX |
鼠标相对于电脑屏幕的X坐标 |
e.screenY |
鼠标相对于电脑屏幕的Y坐标 |
javascript
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>18.鼠标在页面中的坐标</title>
<style>
body{
height: 3000px;
}
</style>
</head>
<body>
<script>
//鼠标事件对象
document.addEventListener('click',function(e){
//1.client 鼠标在可视区的x和y坐标
console.log('clientX---->' + e.clientX);
console.log('clientY---->' + e.clientY);
//2.page 鼠标在页面文档的x和y坐标
console.log('pageX---->' + e.pageX);
console.log('pageY---->' + e.pageY);
//3.screen 鼠标在电脑屏幕的x和y坐标
console.log('screenX---->' + e.screenX);
console.log('screenY---->' + e.screenY);
});
</script>
</body>
</html>