目录
1.事件代理
网页设计中的一种设计思想,利用事件对象中引用的目标对象这个技术来实现的
无论事件触发时,是不是目标对象的监听器,在监听器内部的事件对象event中都可以访问这个事件的目标对象(通过envet.target 得到触发事件的目标),利用这个特点去绑定事件给父级元素,来代理子集元素的业务,这种设计就是事件代理。
特点是:给父级元素绑定一个点击事件,通过event.target来判断是哪个子元素被点击了,以此判断点击的子元素和非点击的子元素。
<body>
<style>
.box1{
background-color: darkgray;
}
.box2{
width: 120px;
height: 40px;
background-color: firebrick;
margin: 10px;
}
</style>
<div class="box1">
<div class="box2">hello1</div>
<div class="box2">hello2</div>
<div class="box2">hello3</div>
<div class="box2">hello4</div>
</div>
<script>
//业务,点击谁就打印谁的内容
var box2s = document.querySelectorAll('.box2');
box2s.forEach(el=>{
el.addEventListener('click',function(e){
console.log(this.innerHTML);
})
})
</script>
</body>
分析:点击子元素就会打印出相应的内容
这样设计有两个缺点:
1.静态的事件绑定,如果动态的添加元素进去,添加进去的元素没有这个事件
<body>
<style>
.box1{
background-color: darkgray;
}
.box2{
width: 120px;
height: 40px;
background-color: firebrick;
margin: 10px;
}
</style>
<div class="box1">
<div class="box2">hello1</div>
<div class="box2">hello2</div>
<div class="box2">hello3</div>
<div class="box2">hello4</div>
</div>
<button id="btn" onclick="load1()">点击添加一个新子元素hello5</button>
<script>
//业务,点击谁就打印谁的内容
var box2s = document.querySelectorAll('.box2');
box2s.forEach(el=>{
el.addEventListener('click',function(e){
console.log(this.innerHTML);
})
})
//添加新的子元素
function load1(){
var box1 = document.querySelector('.box1');
var newbox2 = document.createElement('div');
newbox2.classList = 'box2';
newbox2.innerHTML = 'hello5';
box1.appendChild(newbox2);
}
</script>
</body>
分析:点击新添加进去的子元素hello5 并不会触发点击事件,还需要重新给其添加点击事件。
这样一套操作下来就很麻烦。。。。
2. 性能消耗更高 ,业务比较重复
像上面的代码,forEach循环只有一个,但是会生成4个监听器,给每一个子元素都.box2都设置一个,不管子元素是否触发都设置一个监听器,业务相同,设置4个,太浪费内存,也消耗性能。
利用事件代理来解决上面两个问题:
绑定事件给box2的父级box1绑定:通过事件流,
<body>
<style>
.box1 {
background-color: darkgray;
}
.box2 {
width: 120px;
height: 40px;
background-color: firebrick;
margin: 10px;
}
</style>
<div class="box1">
<div class="box2">hello1</div>
<div class="box2">hello2</div>
<div class="box2">hello3</div>
<div class="box2">hello4</div>
</div>
<button id="btn" onclick="load1()">点击添加一个新子元素hello5</button>
<script>
//业务,点击谁就打印谁的内容
var box1 = document.querySelector('.box1');
box1.addEventListener('click', function (e) {
console.log(e.target.innerHTML); //根据事件流,谁触发了box1绑定的点击事件,event.target就是谁
})
//添加新的子元素
function load1() {
var box1 = document.querySelector('.box1');
var newbox2 = document.createElement('div');
newbox2.classList = 'box2';
newbox2.innerHTML = 'hello5';
box1.appendChild(newbox2);
}
</script>
</body>
分析:新添加的子元素hello5,没有再去给其设置点击事件。事件代理实现了,给父级元素box1绑定一个点击事件,所有子元素都能被监听(谁触发就target指谁)。给父级元素box1绑定一个点击事件,完成了给所有子元素设置相同绑定事件的工作量。
2.一些额外的技术
1.document可以绑定事件
document虽然是一个看不到的元素,但是其是处于事件链中的一部分,可以绑定事件
document.onclick = function(){}
2. event.target 和 event.srcElement都可以获取事件的目标对象(事件的触发者)
3.获取根元素:document.documentElement
console.log(document.documentElement); //html
4.获取根节点:document
console.log(document);
根节点的范围比根元素更广。
5.获取body元素:document.body
console.log(document.body); //body
6.元素可以绑定一些自定义属性 data-自定义 data- 是固定写法
取属性的时候是 元素.dataset 固定写法取
<body>
<div id="box5" data-blue="999" data-src1="www.123456789.com"></div>
<script>
var box5 = document.querySelector('#box5');
console.log(box5.dataset);
</script>
</body>
分析:这些自定义属性都是在一个对象里面,它的构造函数是DOMStringMap。
7.document.write(); 它所在脚本在哪个标签里面,就在哪个标签里面写内容
<body>
<script>
console.log(document.write('脚本script在body里面,在body里面写内容'));
</script>
</body>