DOM0
事件和DOM2级
在事件监听使用方式上有什么区别?
-
DOM0
是将代码写进HTML
标签内,例如<a href='#' onclick="console.log('1')">控制台输出1</a>
- 优点:
- 浏览器兼容性好
- 事件绑定速度快,不用等到js文件下载完
- 缺点:
- 如果
onclick
使用的是js文件中的函数,js文档加载时用户点击会没有反应 - 不易于维护,每次都需要修改
HTML
代码和'JavaScript'代码 - 只能绑定一个事件,无法绑定多个处理程序,这种方法一个事件只能绑定一个处理程序,如果写多个,后面的处理程序会将前面的覆盖
- 如果
- 优点:
- 'DOM2级'事件通过
addEventListener
,removeEventListener
两个方法在js文件中处理和删除事件处理程序的操作- 优点:
- 易于维护,每次只修改
JavaScript
代码就好 - 可以绑定多个事件
- 易于维护,每次只修改
- 缺点:
-
IE
需要使用能力判断
-
- 优点:
attachEvent
与addEventListener
的区别?
- 参数个数不同:
addEventListener
有三个参数,attachEvent
只有两个参数 - 事件发生的阶段不同:
addEventListener
的第三个参数可以决定添加的事件实在捕获阶段还是冒泡阶段,而IE只能发生在冒泡阶段 - 第一个参数意义不用,addEventListener是事件类型(
click
,load
),而attachEvent是事件处理的函数名(onclick
,onload
) - 事件处理程序的作用域不同,
addEventListener
的作用域是元素本身,而attachEvent
的作用域是window
- 为一个事件添加多个处理程序的时候,顺序不一样:
addEventListener
是按照添加顺序添加的,而attachEvent
是随机添加的
解释IE事件冒泡
和DOM2事件传播机制
- IE事件冒泡
- 由最子元素接受,然后一次向上传递,直到文档的根节点document
- DOM2事件传播机制
- 分为三个阶段:事件捕获阶段,处于目标阶段,事件冒泡阶段
- 事件捕获阶段:事件从顶级文档树节点一级一级向下遍历,直到到达该事件的目标节点。
- 处于目标阶段:到达事件的目标节点,执行目标节点的时间处理程序。
- 事件冒泡阶段:与IE事件一样
- 分为三个阶段:事件捕获阶段,处于目标阶段,事件冒泡阶段
如何阻止事件冒泡? 如何阻止默认事件?
- 阻止事件冒泡
function stopPropagation(e) { if (e.stopPropagation) e.stopPropagation(); else e.cancelBubble = true; }
- 阻止默认事件
function preventDefault(e) { if (e.preventDefault) e.preventDefault(); else e.returnValue = false; }
有如下代码,要求当点击每一个元素li时控制台展示该元素的文本内容。不考虑兼容
```
<ul class="ct">
<li>这里是</li>
<li>饥人谷</li>
<li>前端6班</li>
</ul>
```
```
<script>
var lis = document.getElementsByTagName('li')
for(var i=0;i<lis.length;i++){
lis[i].addEventListener('click',function(){
alert(this.innerHTML)
},false)
}
</script>
```
补全代码,要求:
当点击按钮开头添加时在<li>这里是</li>
元素前添加一个新元素,内容为用户输入的非空字符串;当点击结尾添加时在最后一个 li 元素后添加用户输入的非空字符串
当点击每一个元素li时控制台展示该元素的文本内容。
<ul class="ct">
<li>这里是</li>
<li>饥人谷</li>
<li>任务班</li>
</ul>
<input class="ipt-add-content" placeholder="添加内容"/>
<button id="btn-add-start">开头添加</button>
<button id="btn-add-end">结尾添加</button>
<script>
var lis = document.getElementsByTagName('li')
for(var i=0;i<lis.length;i++){
lis[i].addEventListener('click',function(){
alert(this.innerHTML)
},false)
}
var ul = document.querySelector('.ct')
var inputValue = document.querySelector('.ipt-add-content')
var btnAddStart = document.getElementById('btn-add-start')
var btnAddEnd = document.getElementById('btn-add-end')
btnAddStart.addEventListener('click',function(){
var newItem = document.createElement('li')
newItem.innerText = inputValue.value
ul.insertBefore(newItem,ul.firstChild)
},false)
btnAddEnd.addEventListener('click',function(){
var newItem = document.createElement('li')
newItem.innerText = inputValue.value
ul.appendChild(newItem)
},false)
</script>
补全代码,要求:当鼠标放置在li元素上,会在img-preview里展示当前li元素的data-img对应的图片。
<ul class="ct">
<li data-img="1.png">鼠标放置查看图片1</li>
<li data-img="2.png">鼠标放置查看图片2</li>
<li data-img="3.png">鼠标放置查看图片3</li>
</ul>
<div class="img-preview"></div>
<script>
var lis = document.getElementsByTagName('li')
var imgPreview = document.querySelector('.img-preview')
for(var i=0;i<lis.length;i++){
lis[i].addEventListener('mouseover',function(){
var img =document.querySelector('.img-preview>img')
if(document.querySelector('.img-preview>img')===null){
var newImg = document.createElement('img');
newImg.src= this.getAttribute('data-img')
imgPreview.appendChild(newImg)
}
},false)
lis[i].addEventListener('mouseout',function(){
var img =document.querySelector('.img-preview>img')
img.parentNode.removeChild(img)
},false)
}
</script>
面试的时候被问到了时间代理和委托,让我用原生js实现一下,当时没有回答上来。于是又恶补了一番。
当一个ul
或者ol
中有多个li
元素的时候,我们不必一个一个的给每个li
添加时间,以下大多数人能想到的方式
<ul id='container'>
<li>点我1</li>
<li>点我2</li>
<li>点我3</li>
<li>点我4</li>
</ul>
let items = document.querySelectorAll('#click-container > li')
for(let i=0;i<items.length;i++){
items[i].addEventListener('click',function(e){
console.log(e.target)
},false)
}
事件冒泡大家都应该知道,我们可以利用事件冒泡来获取用户点击的标签。先看代码。
let clickContainer = document.getElementById('click-container')
clickContainer.addEventListener('click',function(e){
if(e.target.nodeName.toUpperCase() === 'LI'){
console.log(e.target)
}
},false)
代码很简单,大致的原理就是在冒泡阶段监听整个ul
的点击时间,通过e.target
判断用户到底点的是哪个li
,我想如果我当时能说出这么多的话应该不会挂的那么快...