close

最近利用時間做了一個 Vuetify 的 side project

一邊問著 google 大神,一邊慢慢實作自己的想法

竟然也讓我做出一個不錯用的 IG 照片閱覽功能

 

基本上就是憑著寫 Android 的概念

配合 Vuetify 的官網 Document

還有 W3CSHOOL 的基礎知識,慢慢湊起來的

實在不懂的時候問一下公司的前端高手,也是一帖特效藥

點我看 Vue 官方文檔

點我看 W3CSCHOOL CSS 文檔

 

=== 問題開始 ===

因為寫 APP 的時候也用 Firebase 的 Firestore

所以自然而然就想說 DB 就用 Firestore 

除了熟悉之外,也是滿方便的

但最近在使用的時候發生了一些問題

是 Firestore 使用不當造成的

 

我在切換照片的時候

會先閃出 a照片,再 show b 照片

而且一開始不會有事

要到有幾次換頁面 (跳頁) 才會發生

重點是,只有在 safari 出現,chrome 不會

 

一直聽說前端 browser 很多坑

沒想到剛入新手村的我就這樣被 safari 搞了一次

我看著 log 發現我的 photo 物件被 DB 塞了兩次值

難怪會有切一次照片,跳兩次的情況

 

由於 Firestore 支援即時更新

也就是說我如果在另一個裝置上增加了照片 or 評論

其餘的裝置會同步的收到,並更新

或是我的 Python 爬蟲抓內容的時候,也會同步更至最新

要做到這件事,我們就必需和 Firestore 建立一條不斷的連線

讓內容能持續的被更新

 

現在這種情況很明顯就是連線被監聽了兩次

我們有了兩條不斷的連線

為什麼偏偏只有 safari 會有這個情況呢?

上網 google 後發現其它人也有遇過

大多是 safari 的 cache 機制造成的

我們 A 頁起了一個連線,跳到 B 頁後再回 A 頁

這樣第二次的 A 頁 cache 保存了舊連線並建立了新連線

造成共存的情況

 

那要怎麼解呢?

我想了好幾個方法,試了很多次

最後得出 3 個解法

1、不要建立不斷連線、使用 Firestroe once getting 的 function

2、使用 Javascript 的 window.addEventListener 監聽 event

3、使用 Vue 的 beforeDestroy 在頁面跳出前,做取消訂閱 Firestore 的動作

 

第一種如果有特別需要保持更新的人

可能就沒辦法使用,在此不推薦

 

第二種的做法就像這樣

window.addEventListener('popstate', function(event))


popstate 是一個 history 下的 event 

只會在 history entry 變動時被 trigger

也就是說,不論跳頁、上一頁、下一頁…等

都會改變到 history entry 而觸發

這樣雖然可以達到目的

不過會造成很多額外的觸發,這邊也較不推薦

這裡有 window 的 event 大全

若有特別需要的人,可以來這邊找找有沒有適合的 event 可用

點我看 Window Events

 

最後的第三種
是利用 Vue Component 的生命週期來處理,如下圖

The Vue Instance Lifecycle

圖片來源
 

這個有點像 Android Activity Lifecycle 一樣

Vue 也有類似的 create ~ destroy 等狀態

比如說我們的 Firestore 連線就是在 created 建立的,如下

export default {
    components: {},
    data: () => ({
        photo: Object,
        dbUnsubscribe: Object
    }),
    methods: {
        dbUnsubscribeFunc() {
            // 終止 db 連線
            this.dbUnsubscribe();
        }
    },
    computed: {},
    created() {
        // 建立 db 連線
        this.queryShowPhotoByAcc();
    }
};


所以我們可以利用生命周期的 beforeDestroy

來達到我們的目的

不過 beforeDestroy 只能監聽到頁面跳換

無法監聽到頁面刷新和關閉標籤頁。

若是想要監聽的話,就要用方法二的 onbeforeunload event 了

 

好,最後,我們利用 beforeDestroy 把 code 改成下面這樣

created() {
    // 建立 db 連線
    this.queryShowPhotoByAcc();
},
beforeDestroy() {
    this.dbUnsubscribeFunc();
}


完成!!!

想了解更多的生命週期可以看這裡

點我看 Vue Component Lifecycle

 

 

 

 

 

資料來源:

https://vuetifyjs.com/en/getting-started/quick-start

https://developer.mozilla.org/en-US/docs/Web/API/Window#Events

https://vuejs.org/v2/guide/instance.html


arrow
arrow

    顏澤偉 發表在 痞客邦 留言(0) 人氣()