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: hidden
和opacity: 0
都被视作可见的,因为它们在页面上占据了相应的物理空间。