vue v-for 列表更新導致 iframe 刷新而狀態丟失的原因以及恢復狀態的方案
因為當列表數據變化,vue 重新渲染列表時,會導致受影響的列表項的 DOM 從頁面移除,而 iframe 被移除后再添加回頁面一定會刷新。
如果向列表的數據數組的開頭或中間插入元素,又或者移除元素,vue 會將操作位置對應的 DOM 元素和之后的 DOM 元素統統移除,然后在添加回去。
沒看過 vue 源碼,但是可以推斷,這一過程可能是,先移除所有受影響的元素,然后再將可用的元素添加到合適的位置;這一過程也有可能是使用 Element.replaceWith() 完成的,而該 API 也會將 DOM 元素從頁面中移除。從頁面移除 iframe,iframe 的 contentWindow 會銷毀加載的內容,重新添加到頁面,contentWindow 會重新加載 iframe 指定的 src,這一來一回,就導致了 iframe 狀態丟失。
基于 vue 這個更新列表 DOM 的原理,最好不在列表中使用 iframe。
如果列表數據不變,或者將列表數據當作一個棧來使用,那么不會有 DOM 被移除后重新添加回頁面,這種情況下可以在列表中使用 iframe 。
如果列表數據多變,不僅僅是只操作數據尾部,還會向列表其它位置進行插入或刪除操作,可以考慮通過窗口通信的方式來實現狀態的保存與恢復。
- 同域名的網頁,可以直接取得 iframe 的 contentWindow 對象,然后就可以讀取狀態了。contentWindow unload 的時候保存狀態,再將狀態附加到 iframe 的 src 屬性上,iframe 重新添加回頁面時,內部頁面通過 location.href 來恢復狀態。
- 跨域的頁面,使用
window.postMessage來通信,contentWindow unload 的時候將其狀態發送給調用它的頁面,然后調用它的頁面將狀態數據格式化后附加到 iframe 的 src 屬性上。數據恢復的過程和同源網頁沒差。
保存與恢復 iframe 狀態的做法還是有些復雜的,如果在 vue 列表中使用 iframe 是必要的,就好好設計一下 iframe 狀態的保存與恢復的功能。
如果是不必要的,果斷放棄。

浙公網安備 33010602011771號