前端系统课程 - 32. DOM 事件

DOM 事件模型

  • e.stopPropagation() 方法可以阻止事件冒泡。

  • e.preventDefault() 方法可以阻止元素的默认事件。

  • 阻止默认事件可能会带来一些意外的 bug,例如复选框不能选中等等。

  • 如果想让 jQuery 中的 on() 方法同时阻止默认事件和阻止冒泡,可以直接在回调函数参数后,再传一个 false 参数。

  • 为元素绑定事件监听是需要占用内存的,所以一个监听事件完成后,在非必须的情况下,尽量把这个事件监听再解除掉;在 jQuery 中,善用一次性事件监听 one() 方法。

  • 如果在一个事件监听的回调函数中,又对其上级元素绑定了事件监听,那么这个后绑定的事件监听,在前一个事件触发后会立即完成绑定,并在本次的事件触发过程中生效。例如:

    1
    2
    3
    4
    5
    6
    $('#son').on('click', () => {
    console.log('子元素被点击了');
    $('#father').one('click', () => {
    console.log('父元素被点击了'); // 本来觉得这里不会执行,但确实会执行;
    });
    });

    如果不想让父元素事件监听的回调函数执行,最好的办法就是在子元素添加阻止冒泡;也可以使用延时定时器延迟对父元素事件监听的绑定,即使定时器设置为 0 秒,也会让绑定动作在事件触发完成以后执行,但只能延迟一轮,再次点击子元素,父元素由于绑定已经在上一次点击完成了,所以还会触发。

优化无缝轮播

  • 先前做的无缝轮播有个 bug,如果切换到别的页面一段时间后再切回来,轮播动画会出错(表现为多个动画同时执行),这是因为浏览器为了节省资源,会降低非展示状态的页面中的定时器运行频率。

  • visibilitychange 事件,称为“标签可见性改变事件”;这个事件可以知道用户有没有在看自己,如果用户切换了标签或页面,那么 document.hidden 属性便为 true,反之则反。

  • 通过判断页面的 document.hidden 属性值,来随时控制定时器的关闭和开启,就可以解决前面的轮播动画问题了。

  • 通过切换 class 属性的方式做可切换的无缝轮播非常困难,所以要换一种方式;当实现一个功能发现走到死胡同时,要勇于试错;

  • 用到的 jQuery API:

    • clone() 方法,复制一个元素,传入 true 表示同时复制其子元素,这与DOM API 的 cloneNode() 方法类似。

    • append() 方法,将一个元素插入到目标元素的末尾。

    • prepend() 方法,将一个元素插入到目标元素的首位。

    • offset() 方法,获取或设置元素当前的偏移位置;由于获取时要计算样式,所以会暂时阻断 CSS 解析,可以利用这点来防止与后面准备设置的 CSS 内容合并。

    • on() 方法还可以通过父元素为所有子元素绑定事件,通过选择器来指定子元素,称为“事件委托”,例如:

      $('father').on('click', '.son', function(){ ...somecode });

    • innerWidth() 方法可以获取元素边框以内的宽度,innerHeight() 同理。

    • is() 方法可以查看元素是否匹配选择器;例如使用此方法判断元素的隐藏状态,并切换元素的隐藏状态(可替代废弃的 toggle() 方法):

      $('#test').on('click', () => $('.div').is(':hidden') ? $('.div').show() : $('div').hide());

课后拾遗

  • 在 jQuery 中,为元素添加自定义属性,要么通过下标 0,要么使用 attr() 方法,必须将属性添加到 DOM 元素上,特别是动画中的定时器对象。

  • 再次理解动画原理,元素的位置(或其他可用属性)在指定时间间隔,逐渐改变,直到达到设定的目标位置;体现到属性值上,属性值不停的累加,每次累加计算好的数量,直到此属性值到达设定的目标值。

  • 如果需要一个开关来表示是否到达目标值,直接判断当时值和目标值是否相等,把结果赋值给开关变量,无需进行判断;例如:let ok = current === target

  • 在 jQuery 中,visibility: hiddenopacity: 0 都被视作可见的,因为它们在页面上占据了相应的物理空间。