JS基础回顾_事件基础

this 指向

  • addEventListener: dom
  • attachEvent: dom
  • onXXX: window

如何解决 IE 的 bug?

div.attachEvent('click', function () {
  handle.call(div)
})
function handle() {
  // 事件处理函数
}

考虑兼容性的事件处理函数

/**
 * 考虑兼容性的事件处理函数
 */
function addEvent(element, type, handle) {
  if (element.addEventListener) {
    element.addEventListener(type, handle, false)
  } else if (element.attachEvent) {
    element.attachEvent('on' + type, function () {
      handle.call(element) // 改变this指向
    })
  } else {
    element['on' + type] = handle
  }
}

addEventListener 一个事件处理函数只能被绑定一次。这和 attachEvent(IE)不同。

<!-- log -->
<button id="event_test_1">点我</button>
<script>
  let element = document.getElementById('event_test_1')
  element.addEventListener('click', test, false)
  element.addEventListener('click', test, false)
  function test() {
    alert('click')
  }
</script>
<!-- log -->
<button id="event_test_2">点我</button>
<script>
  let element = document.getElementById('event_test_2')
  element.addEventListener(
    'click',
    function () {
      alert('click')
    },
    false
  )
  element.addEventListener(
    'click',
    function () {
      alert('click')
    },
    false
  )
</script>

解除事件绑定函数

ele.onclick = false / null
ele.removeEventListen(type, fn, false)
ele.detachEvent('on' + type, fn)

冒泡和捕获

事件冒泡:结构上自子元素传递到父元素

测试冒泡
1
2
3
测试捕获
1
2
3
// run
let thePop = document.getElementById('thePop')
{
  let div1 = thePop.getElementsByClassName('div1')[0]
  let div2 = thePop.getElementsByClassName('div2')[0]
  let div3 = thePop.getElementsByClassName('div3')[0]
  div1.addEventListener(
    'click',
    function () {
      alert('div1')
    },
    false
  )
  div2.addEventListener(
    'click',
    function () {
      alert('div2')
    },
    false
  )
  div3.addEventListener(
    'click',
    function () {
      alert('div3')
    },
    false
  )
}
{
  let theCatch = document.getElementById('theCatch')
  let div1 = theCatch.getElementsByClassName('div1')[0]
  let div2 = theCatch.getElementsByClassName('div2')[0]
  let div3 = theCatch.getElementsByClassName('div3')[0]
  div1.addEventListener(
    'click',
    function () {
      alert('div1')
    },
    true
  )
  div2.addEventListener(
    'click',
    function () {
      alert('div2')
    },
    true
  )
  div3.addEventListener(
    'click',
    function () {
      alert('div3')
    },
    true
  )
}

事件捕获:只在 Chrome 可用

如果既有捕获也有冒泡,则顺序为

  • 捕获
  • 事件
  • 冒泡

特殊事件不会冒泡和捕获

  • focus
  • blur
  • change
  • submit
  • reset
  • select

取消冒泡

e.stop
e.cancleBubble = true

function stopBubble() {
  if (e.stopPropagation) {
    e.stopPropagation
  } else {
    e.cancleBubble = true
  }
}

取消默认事件

  • return false(仅支持句柄的方式)
  • e.preventDefault()
  • e.returnValue = false

test_default

// no-log
let a = document.getElementById('test_default')
a.onclick = function (e) {
  alert('默认事件被取消了')
  cancleHandler(e)
}
function cancleHandler(event) {
  if (event.preventDefault) {
    event.preventDefault()
  } else {
    event.returnValue = false
  }
}

事件源对象

<!-- log -->
<!-- 粗暴方式 -->
<div id="container_1">
  <button>1</button>
  <button>2</button>
  <button>3</button>
  <button>4</button>
  <button>5</button>
</div>
<script>
  let container = document.getElementById('container_1')
  let btnList = container.getElementsByTagName('button')
  for (let i = 0; i < btnList.length; i++) {
    btnList[i].onclick = function () {
      alert(this.innerText)
    }
  }
</script>
<!-- log -->
<!-- 事件委托 -->
<div id="container_2">
  <button>1</button>
  <button>2</button>
  <button>3</button>
  <button>4</button>
  <button>5</button>
</div>
<script>
  let container = document.getElementById('container_2')
  container.onclick = function (e) {
    let event = e || window.event
    let target = event.target || event.srcElement
    alert(target.innerText)
  }
</script>

事件委托机制的优点

  • 性能好,不需要循环所有的元素一个个地绑定事件
  • 灵活,当有新的子元素时不需要重新绑定

拖拽

<!-- log -->
<!-- 鼠标事件,仅在PC端有效 -->
<div id="moving_box_container">
  <div id="moving_box" style="left: 0;top: 0;  position: absolute; width:50px;height: 50px;background: blueviolet"></div>
</div>
<style>
  #moving_box_container {
    position: relative;
    height: 200px;
    max-width: 800px;
    margin: 0 auto;
    border: 1px solid black;
  }

  #moving_box {
    left: 0;
    top: 0;
    position: absolute;
    z-index: 9999;
    width: 50px;
    height: 50px;
    background: blueviolet;
  }
</style>
<script>
  let box = document.getElementById('moving_box')
  box.onmousedown = function (e) {
    // -- 等式:鼠标相对于文档的位置     ===     父元素的偏移 + left + 鼠标相对box的位置
    // -- 等式:鼠标相对于文档的位置     ===          一      +  二  +      三
    // 暂存 一 + 三
    let disX = e.pageX - parseInt(box.style.left)
    let disY = e.pageY - parseInt(box.style.top)
    // 防止鼠标移动过快,box监听不到
    // box.onmousemove = function (e) {
    document.onmousemove = function (e) {
      let event = e || window.event
      box.style.left = event.pageX - disX + 'px'
      box.style.top = event.pageY - disY + 'px'
    }

    document.onmouseup = function () {
      document.onmousemove = null
    }
  }
</script>
posted @ 2020-08-29 14:12  oceans-pro  阅读(128)  评论(0)    收藏  举报