javascript
js如何监听元素事件是否被移除_JavaScript 监听元素是否进入/移出可视区域
JavaScript 監聽元素是否進入/移出可視區域
常規操作
防抖節流
IntersectionObserver
兼容的代碼
常規操作
通常的做法是,監聽srcoll事件,根據元素的offset來判斷。
window.addEventListener('scroll', this.scrollHandle, true);
使用getBoundingClientRec()來獲取元素的位置。
scrollHandle () {
const offset = this.$el.getBoundingClientRect(); // vue中,使用this.$el獲取當前組件的根元素
const offsetTop = offset.top;
const offsetBottom = offset.bottom;
const offsetHeight = offset.height;
// 進入可視區域
if (offsetTop <= window.innerHeight && offsetBottom >= 0) {
console.log('進入可視區域');
// do something...
} else {
console.log('移出可視區域');
// do something...
}
}
記得在適當的時候移除事件監聽
window.removeEventListener('scroll', this.scrollHandle, true);
但是這種操作,使得我們的開銷變得很大,所以可以考慮防抖和節流。
防抖節流
關于防抖和節流,看過不一樣的理解,有的人認為防抖和節流是一個意思,在這里,按照我的理解,給防抖和節流的定義如下:
防抖:在停止觸發一段時間后再調用方法;
節流:再一段時間內至少調用一次方法;
具體的原理就不講了,直接上代碼,iselapsed參數表示是否等待上一次,也就是iselapsed為true,則為節流。
/**
* 防抖節流
* @param {*} action 回調
* @param {*} delay 等待的時間
* @param {*} context this指針
* @param {Boolean} iselapsed 是否等待上一次
* @returns {Function}
*/
function throttle (action, delay, context, iselapsed) {
let timeout = null;
let lastRun = 0;
return function () {
if (timeout) {
if (iselapsed) {
return;
} else {
clearTimeout(timeout);
timeout = null;
}
}
let elapsed = Date.now() - lastRun;
let args = arguments;
if (iselapsed && elapsed >= delay) {
runCallback();
} else {
timeout = setTimeout(runCallback, delay);
}
/**
* 執行回調
*/
function runCallback() {
lastRun = Date.now();
timeout = false;
action.apply(context, args);
}
};
}
在這里,我希望方法在一段時間內至少執行一次,所以我用節流
window.addEventListener('scroll', this.scrollHandle, true);
this.scrollHandle = throttle(this.scrollThrottle, 200, this, true)
scrollThrottle () {
const offset = this.$el.getBoundingClientRect();
const offsetTop = offset.top;
const offsetBottom = offset.bottom;
const offsetHeight = offset.height;
// 進入可視區域
if (offsetTop <= window.innerHeight && offsetBottom >= 0) {
console.log('進入可視區域');
// do something...
} else {
console.log('移出可視區域');
this.enabledPause = false;
// do something...
}
}
IntersectionObserver
安卓設備和部分瀏覽器支持IntersectionObserver來通知我們元素進入/移出可視區域。
判斷是否支持IntersectionObserver:
if ('IntersectionObserver' in window &&
'IntersectionObserverEntry' in window &&
'intersectionRatio' in window.IntersectionObserverEntry.prototype) {
// do something
}
創建IntersectionObserver,并傳入回調,指定進入/移出可視區域時的操作。還可以傳入一個對象({threshold, root}),用來配置IntersectionObserver。
threshold屬性決定了什么時候觸發回調函數。它是一個數組,每個成員都是一個門檻值,例如[0, 0.25, 0.5, 0.75, 1]。默認為[0],即交叉比例(intersectionRatio)達到0時觸發回調函數。
root屬性用來指定根元素。
callback函數的參數entries是一個數組,每個成員都是一個IntersectionObserverEntry對象,其中的intersectionRatio屬性表示監聽的元素與根元素的交叉的比例,>0則表示此時進入可視區域。
this.observer = new IntersectionObserver(entries => {
if (entries[0].intersectionRatio > 0) {
console.log('進入可視區域');
// do something
} else {
console.log('移出可視區域');
// do something
}
});
開始監聽
this.observer.observe(this.$el);
取消監聽
this.observer.disconnect();
兼容的代碼
因為iOS不支持IntersectionObserver,所以我們要在不支持的時候繼續監聽scroll事件。
貼上完整的代碼
import throttle from '../throttle.js';
export default {
data () {
return {
observer: null,
scrollHandle: throttle(this.scrollThrottle, 200, this, true)
};
},
mounted () {
// 判斷是否支持 IntersectionObserver
if ('IntersectionObserver' in window &&
'IntersectionObserverEntry' in window &&
'intersectionRatio' in window.IntersectionObserverEntry.prototype) {
this.observer = new IntersectionObserver(entries => {
if (entries[0].intersectionRatio > 0) {
console.log('進入可視區域');
// do something
} else {
console.log('移出可視區域');
// do something
}
});
}
},
methods: {
startObserve () {
if (this.observer) {
this.observer.observe(this.$el);
} else {
window.addEventListener('scroll', this.scrollHandle, true);
}
},
endObserve () {
if (this.observer) {
this.observer.disconnect();
} else {
window.removeEventListener('scroll', this.scrollHandle, true);
}
},
scrollThrottle () {
const offset = this.$el.getBoundingClientRect();
const offsetTop = offset.top;
const offsetBottom = offset.bottom;
const offsetHeight = offset.height;
// 進入可視區域
if (offsetTop <= window.innerHeight && offsetBottom >= 0) {
console.log('進入可視區域');
// do something
} else {
console.log('移出可視區域');
// do something
}
}
}
}
throttle.js
/**
* 回調節流
*
* @export
* @param {*} action 回調
* @param {*} delay 等待的時間
* @param {*} context this指針
* @param {Boolean} iselapsed 是否等待上一次
* @returns {Function}
*/
export default function throttle (action, delay, context, iselapsed) {
let timeout = null;
let lastRun = 0;
return function () {
if (timeout) {
if (iselapsed) {
return;
} else {
clearTimeout(timeout);
timeout = null;
}
// return;
}
let elapsed = Date.now() - lastRun;
let args = arguments;
if (iselapsed && elapsed >= delay) {
runCallback();
} else {
timeout = setTimeout(runCallback, delay);
}
/**
* 執行回調
*/
function runCallback() {
lastRun = Date.now();
timeout = false;
action.apply(context, args);
}
};
}
總結
以上是生活随笔為你收集整理的js如何监听元素事件是否被移除_JavaScript 监听元素是否进入/移出可视区域的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 电脑键盘上如何打顿号(怎么用电脑键盘打顿
- 下一篇: 呱啦鸡是保护动物吗 呱啦鸡是不是保护动物