JavaScript事件

227 阅读3分钟

问:JavaScript动画与CSS3动画有什么区别?

答:优先选择css设置动画,因为不需要进行js解析,不会改变已经渲染好的dom树,也就不会引起重绘或者回流,性能好,但是css对于动画的控制较弱,所以中间控制过程较多的复杂动画需要用js实现,或者CSS3出现兼容问题,选择js动画

问:DOM事件模型?如何阻止事件冒泡、默认行为?

答:

<1> DOM事件模型分为两种:事件捕获和事件冒泡

事件捕获模型里目标元素触发事件,事件会从根开始,依次传过目标元素的上级元素,传到目标元素,事件所经过的元素全部触发事件;

事件冒泡模型里目标元素触发事件,事件会从目标元素开始,依次传过目标元素的上级元素,直到根,事件所经过的元素全部触发事件;

<2>

2.1 阻止事件冒泡和事件的默认行为

自定义一个事件处理函数,返回false,取消事件,可以同时阻止事件冒泡与事件默认行为

2.2 阻止事件冒泡

方法1: W3C方法用e.stopPropagation(),IE浏览器不支持,IE用e.cancelBubble(),封装一个方法判断浏览器类型,选择对应的方法阻止冒泡

function bubbles(e){
let ev = e || window\.event
if(ev&\&ev.stopPropagation){
//非IE浏览器
ev.stopPropagation()
}else{
//IE浏览器(IE11以下)
ev.cancelBubble = true
}
}

方法2:e.stopImmediatePropagation(),阻止后续事件处理函数执行,不论是目标元素的事件监听,还是上级元素的事件监听

   <div>
    <a href="https://juejin.cn/" id="testA">a跳转</a>
  </div>
<script>
  document.querySelector('div').addEventListener('click',(e)=>{
  //补充:e.target是触发事件的元素,e.currentTarget是绑定当前事件监听的对象
    console.log('div事件委托处理',e.target,e.currentTarget)//输出失败
  })
  document.querySelector('#testA').addEventListener('click',(e)=>{
    e.preventDefault() //阻止默认行为                      
    e.stopImmediatePropagation() //阻止后续事件处理函数执行
    //补充:e.stopPropagation()阻止冒泡
  console.log('第1次事件处理',e.target,e.currentTarget)//成功输出
})
document.querySelector('#testA').addEventListener('click',(e)=>{
  e.preventDefault()
  console.log('第2次事件处理',e.target,e.currentTarget)//输出失败
})
</script>

2.3 阻止默认行为

W3C方法用e.preventDefault(),IE浏览器不支持,IE用e.returnValue=false,封装一个方法判断浏览器类型,选择对应的方法阻止默认行为

function defaultB(e){
if(e.preventDefault){
e.preventDefault()
}else{
//a的默认行为,不是click的默认行为,所以用window\.event,不用e
window\.event.returnValue=false
}
}

问:事件三要素?

答:

事件源:触发事件的对象

事件类型:动作,比如点击或者鼠标划过

事件处理函数:事件处理程序

记忆逻辑:事件就是发现用户在哪里(事件源)完成了什么动作(事件类型),规定网页如何处理这个动作(事件处理函数)

问:DOM和BOM的区别

答:BOM是浏览器对象模型,没有自己的通用标准(不一样的浏览器标准肯定不一样,但是主流浏览器大多数js代码大同小异),顶级对象是Window; DOM是文档对象模型,适用W3C标准,顶级对象是Window.document,简写为document

5.编写一个通用的事件监听函数?

//准备一个嵌套盒子
  <div id="outer">
    <a href="https://juejin.cn/" id="inner">a跳转</a>
  </div>
  //js
<script>
  const a =  document.querySelector('#outer')
  //调用函数
bind(a,'click','#inner',(e)=>{
  e.preventDefault()
  console.log(e.target,e.currentTarget)
})
//定义函数
  function bind (ele,type,selector,fn){
  //判断是否事件委托,不是则事件源选择器字符串selector=undefined
   if(fn==null){
      fn=selector,
      selector=undefined
    }
ele.addEventListener(type,(e)=>{
//如果是事件委托,判断事件源与设置监听的事件对象是否相同
  if(selector){
      let target = e.target
      if(target.matches(selector)){
      //更改回调函数this并赋实参e
        fn.call(target,e)
      }else{
        fn(e)
      }}})}