项目背景:当进入页面滚动的时候,页面中的元素出现在视野的时候,展示一下动画效果。
技术栈:vue
实现方法:主要是给需要动画的元素添加animation+X/Y/L/R class样式
解决什么问题:
- 网上的好多滚动事件没有添加防抖函数,这样会导致在滚动过程中会有白屏现象。
- 另外就是没有移除事件监听,在离开当前页面的时候,需要在销毁组件之前移除滚动事件,否则跳转路由之后,事件仍然会被调用,浪费资源
- 为什么不直接
window.addEventListener('scroll', throttle(this.handleScroll, 0, 500))
这样写?因为我发现这样在remove的时候移除不了。所以监听处理写个声明式函数、或者用函数表达式赋值给变量比较好些,这样移除事件监听方便些。
开始吧
/**
* 在 mounted() 的时候(el 被新创建的 vm.$el 替换,并挂载到实例上去之后调用该钩子。)
* 添加事件监听
*/
this.throttleLoad = throttle(this.handleScroll, 0, 500)
window.addEventListener('scroll', this.throttleLoad)
this.handleScroll() // 并首次调用动画(可能有些元素在不同尺寸的屏幕下,有可能需要执行动画)
methods 中监听调用的方法
// 不同页面调用不同的方法
handleScroll(e) {
const clientH = window.innerHeight
const boxListL = [...document.querySelectorAll('.animationL')]
boxListL.forEach((item, index) => {
const Rect = item.getBoundingClientRect()
if (Rect.top + 130 < clientH) {
handleAddClass(item, 'animation-activeL')
} else {
handleRemoveClass(item, 'animation-activeL')
}
})
const boxListR = [...document.querySelectorAll('.animationR')]
boxListR.forEach((item, index) => {
const Rect = item.getBoundingClientRect()
if (Rect.top + 130 < clientH) {
handleAddClass(item, 'animation-activeR')
} else {
handleRemoveClass(item, 'animation-activeR')
}
})
}
}
主动销毁
beforeDestroy() {
window.removeEventListener('scroll', this.throttleLoad)
}
公共的方法抽离出来放到公共js中
// 因为当时考虑到兼容问题,在IE低版本中没有classList.add / remove 这些方法
/**
* Add class
* @param {DOM} item
* @param {className} name
*/
export function handleAddClass(item, name) {
if (item.classList) {
item.classList.add(name)
} else {
const classes = item.className.split(/\s+/g)
if (classes.indexOf(name) < 0) {
classes.push(name)
}
item.className = classes.join(' ')
}
}
/**
* Remove class
* @param {DOM} item
* @param {className} name
*/
export function handleRemoveClass(item, name) {
if (item.classList) {
item.classList.remove(name)
} else {
const classes = item.className.split(/\s+/g)
const n = classes.indexOf('animation-activeL')
if (n > -1) {
classes.splice(n, 1)
}
item.className = classes.join(' ')
}
}
/**
* 防抖
* @param fn 执行的函数
* @param delay 延时时间
* @param atleast 达到强制执行的条件
*/
export function throttle(fn, delay, atleast) {
let timer = null
let previous = null
return function () {
const now = +new Date()
if (!previous) previous = now
if (atleast && now - previous > atleast) {
fn()
previous = now
clearTimeout(timer)
} else {
clearTimeout(timer)
timer = setTimeout(function () {
fn()
previous = null
}, delay)
}
}
}
网友评论