Skip to content

使用 Vue 監聽 iframe 的滾動事件

Posted on:2023/02/23 15:17:00

前言

最近有一個專案,是把注意事項獨立出一個 html 在崁入到主頁面中。需求是滾動完整個 iframe 在顯示再一步,所以需要監聽該滾動事件。 那因為 vue 本身是沒有監聽 iframe 的滾動事件,所以需要使用原生的 js 來監聽。

監聽 iframe 的滾動事件

監聽 iframe 的 scroll 事件,這邊是用 ref 的方式來取得 DOM 元素,並且使用 contentDocument 來取得 iframe 的 DOM 元素。

並監聽 scroll 事件,這邊是用 addEventListener 來監聽,因為 @scroll 這種方式是無法監聽到 iframe 的滾動事件。

要判斷是否滾動到最底部,判斷的方法是

iframe 的高度 - iframe 的滾動高度 === iframe 的可視高度

<iframe ref="notice" src="..." />
<button type="button" :disabled="!isScrollBottom">下一步</button>
data() {
    return {
        isScrollBottom: false
    }
},
methods:{
    listenScroll() {
        const vm = this;
        vm.$refs.notice.contentDocument.addEventListener('scroll', (e) => {
            const iframeBody = vm.$refs.notice.contentDocument.body;
            const isScrollBottom =
                (iframeBody.scrollHeight - iframeBody.scrollTop)
                === iframeBody.clientHeight;

            if (isScrollBottom) {
                vm.isScrollBottom = true;
            }
        });
    }
},

iframe 未監聽到滾動事件

有遇到少部分的 iframe 未監聽到滾動事件,可能是因為 iframe 為動態載入,建議可以在監聽事件前在加上監聽載入完成的事件

vm.$refs.notice.addEventListener('load', () => {
    vm.$refs.notice.contentDocument.addEventListener('scroll', (e) => {
        ...
    });
});

部分舊的 android 取不到 iframe 的 scrollHeight 、scrollTop 、clientHeight

在使用 iframe.contentDocument.body 前,我是使用 contentWindow 來做,確實在 chrome 上可以正常取得,但部份的手機瀏覽器卻讀不出該值,所以改用 contentDocument.body 來取得。

部分瀏覽器在滾動最底部時沒有觸發事件

為了避免部分瀏覽器的差異,我再程式最後加了 50 的高度,可以保證滾動到一個程度時該程式可以正常做觸發。當滾動到離最底部 50px 時,就可以觸發下一步的按鈕。

const isScrollBottom =
  iframeBody.scrollHeight - iframeBody.scrollTop < iframeBody.clientHeight + 50;

if (isScrollBottom) {
  vm.isScrollBottom = true;
}