在继续之前,先回顾一下DOM基础的重点
-
文档对象模型(Document Object Model):是W3C组织推荐的可处理扩展性标记语言(HTML和XML)的标准编程接口(APIs),通过这些DOM接口可以改变网页内容、结构或者样式
-
对于JavaScript,为了能够让其操作HTML,JavaScript拥有一套自己的编程接口
-
对于HTML,DOM使得HTML形成一课DOM树,包含了文档,元素与节点
-
关于DOM操作,主要针对于创建、增加、删除、修改、查询、属性操作、事件操作几个方面
创建
- document.write
- innerHTML
- createElement
增加
- appendChild
- insertBefore
删除
- removeChild
修改
主要针对于DOM元素属性、DOM元素内容、表单的属性和值等
- 修改元素属性:src、href、title等
- 修改普通元素内容:innerHTML、InnerText
- 修改表单元素:value、type、disable
- 修改元素属性:style、className
查询
主要获取查询DOM元素
- DOM提供的API方法:getElementById、getElementByTagName
- H5新增的方法:querySelector、querySelectorAll
- 利用节点操作获取元素:父节点(parentNode)、子节点(children)、兄弟节点(previousElementSibling、nextElementSibling)
属性操作
主要针对自定义属性
- setAttribute:设置dom属性值
- getAttribute:得到dom属性值
- removerAttribute:移除属性
事件操作
获取事件源+事件类型+事件处理程序
事件操作.png
两种注册事件方式
事件注册的两种方式.png addEventListener事件监听方式.png传统方式注册事件
var btns = document.querySelectorAll('button');
// 如果注册多个事件,后面的会覆盖掉前面的事件
btns[0].onclick = function () {
alert('hi');
}
btns[0].onclick = function () {
alert('hao a u');
}
点击按钮,实际只会弹出 'hao a u' 这一个对话框
事件侦听注册事件 addEventListener
- 里面的事件类型是字符串, 必定加引号, 而且不带on
- 同一个元素 ,同一个事件可以添加多个侦听器(事件处理程序)
btns[1].addEventListener('click', function () {
alert(22);
})
btns[1].addEventListener('click', function () {
alert(33);
})
点击按钮,会先弹出22,再弹出33
删除事件
传统方式解绑事件
var btns = document.querySelectorAll('button');
// 传统方式解绑事件
btns[0].onclick = function(){
alert('22');
btns[0].onclick = null;
}
方法监听移除事件 removeEventListener
btns[1].addEventListener('click',fn);
function fn(){
alert('33');
btns[1].removeEventListener('click',fn);
}
DOM事件流
DOM事件流.png事件发生时会在元素节点之间按照特定的顺序传播,这个传播过程即DOM事件流
注意事项:
- JS代码中只能执行捕获或者冒泡其中的一个阶段
- onclick和attachEvent 只能得到冒泡阶段
- addEventListener(type,listener,[useCapture])第三个参数如果是true,表示在事件捕获阶段调用事件处理程序;反之,如果是false(默认),表示在事件冒泡阶段调用事件处理程序
- 实际开发中更多用到的是事件冒泡
- 有些事件是没有冒泡的,比如onblur、onfocus、onmouseenter、onmouseleave
- 事件冒泡有时候会带来麻烦,有时候又会很巧妙的做某些事件
DOM事件流代码验证
html:
<div class="father">
<div class="son">son盒子</div>
</div>
css:
<style>
.father {
overflow: hidden;
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>
image.png
捕获阶段:
如果addEventListener 第三个参数是 true, 那么则处于捕获阶段
var son = document.querySelector('.son');
var father = document.querySelector('.father');
son.addEventListener('click', function () {
alert('son');
}, true);
father.addEventListener('click', function () {
alert('father');
}, true);
顺序:document -> html -> body -> father -> son
实际结果会先弹出father,后弹出son
冒泡阶段:
如果addEventListener 第三个参数是 false或空,那么则处于冒泡阶段
var son = document.querySelector('.son');
var father = document.querySelector('.father');
son.addEventListener('click', function () {
alert('son');
});
father.addEventListener('click', function () {
alert('father');
});
document.addEventListener('click',function(){
alert('document');
})
顺序:son -> father -> body -> html -> document
实际结果会先弹出son,然后是father,最后是document
事件对象
var div = document.querySelector('div');
// div.onclick = function (event) {
// console.log(event);
// }
div.addEventListener('click',function(e){
console.log(e);
})
- event 就是一个事件对象 ,写到我们侦听函数的小括号里面 ,当形参来看
- 事件对象只有有了事件才会存在,它是系统给我们自动创建的,不需要我们传递参数
- 事件对象 是 我们事件的一系列相关数据的集合 ,跟事件相关的 ,比如鼠标点击里面就包含了鼠标的相关信息,鼠标坐标啊,如果是键盘事件里面就包含的键盘事件的信息 ,比如 判断用户按下了那个键
- 这个事件对象我们可以自己命名,比如 event 、 evt、 e
- 事件对象也有兼容性问题 ,ie678 通过 window.event 兼容性的写法 e = e || window.event;
e.target与this的区别
html:
<div>123</div>
<ul>
<li>abc</li>
<li>abc</li>
<li>abc</li>
</ul>
常见事件对象属性和方法:
e.target 返回触发事件的元素(对象)
this 返回绑定事件的元素(对象)
var div = document.querySelector('div');
div.addEventListener('click',function(e){
console.log(e.target);
console.log(this); // 都返回 <div>123</div>
});
var ul = document.querySelector('ul');
ul.addEventListener('click',function(e){
console.log(e.target); // 点击li,返回li标签
console.log(this); // 点击li,返回ul标签
})
返回事件类型与阻止默认行为
返回事件类型
var div = document.querySelector('div');
div.addEventListener('click', fn);
div.addEventListener('mouseover', fn);
div.addEventListener('mouseout', fn);
function fn(e){
console.log(e.type); // 根据鼠标触发事件类型打印出动作行为
}
阻止默认行为,比如让链接不跳转,让提交按钮不提交
var a = document.querySelector('a');
a.addEventListener('click',function(e){
e.preventDefault(); // dom标准写法
});
阻止冒泡
html:
<div class="father">
<div class="son">son儿子</div>
</div>
image.png
阻止冒泡, dom推荐标准 stopPropagation()
var son = document.querySelector('.son');
son.addEventListener('click',function(e){
alert('son');
e.stopPropagation(); // 阻止此元素后面的冒泡阶段
});
var father = document.querySelector('.father');
father.addEventListener('click', function() {
alert('father');
}, false);
document.addEventListener('click', function() {
alert('document');
});
点击son,不会弹出后面的father和document
但是父元素因为没有对冒泡进行阻止,所以如果点击father,还是会弹出'document'
事件委托
事件委托1.png(当然你也可以用循环来给每个li添加事件,这样虽然不难,但是添加事件所占用的内存也多)
- 事件委托:也被称作事件代理,在jQuery里被叫做事件委派
- 事件委托的原理:不是给每个子节点设置事件监听器,而是将监听器设置在父节点上,然后利用事件冒泡原理影响到设置的每个子节点
- 对于上图的案例:先给ul注册点击事件,然后利用事件对象的target来找到当前点击的li,因为点击li,事件会冒泡到ul上,又因为ul有注册事件,就会触发事件监听器
- 事件委托的作用:以上整个过程只添加了一次DOM操作,提高了程序的性能
html:
<ul>
<li>This is a para...</li>
<li>This is a para...</li>
<li>This is a para...</li>
<li>This is a para...</li>
<li>This is a para...</li>
</ul>
js:
<script>
// 事件委托核心:给父节点添加侦听器,利用事件冒泡影响每一个子节点
var ul = document.querySelector('ul');
ul.addEventListener('click',function(e){
// alert('I am clicked !');
// 利用e.target可以得到当前点击对象
e.target.style.backgroundColor = 'aqua';
})
</script>
常见事件
常见鼠标事件
// contextmenu 可以禁用鼠标右键菜单
document.addEventListener('contextmenu',function(e){
e.preventDefault();
});
// selectstart 可以禁止选中文字
document.addEventListener('selectstart',function(e){
e.preventDefault();
})
鼠标事件对象
鼠标事件对象.png键盘事件对象
常用的键盘事件:
- keyup 按键弹起的时候触发
// document.onkeyup = function() {
// console.log('我弹起了');
// }
document.addEventListener('keyup', function () {
console.log('我弹起了');
})
- keydown 按键按下的时候触发
document.addEventListener('keydown', function () {
console.log('我按下了');
})
- keypress 按键按下的时候触发 不能识别功能键 比如 ctrl shift 左右箭头...
document.addEventListener('keypress', function () {
console.log('我按下了press');
})
- 三个事件的执行顺序 keydown -- keypress -- keyup
键盘事件对象:
document.addEventListener('keydown',function(e){
// console.log(e);
console.log(e.keyCode); // 返回按键 ASCII 值
// keyup 和 keydown 不区分字母大小写
})
document.addEventListener('keypress',function(e){
console.log('press:' + e.keyCode); // 返回按键 ASCII 值
// keypress 可以区分字母大小写
// A: 65 a: 97
})
网友评论