首页 > 解决方案 > 在 iframe 内的 Vue 3 实例中延迟注册事件侦听器

问题描述

出于一个非常具体的原因*,我需要一个 Vue 实例在iframe. 我设法在 Vue 论坛上的这个帖子之后做到了这一点,并调整了代码以支持 Vue 3 并删除了插槽,因为我只需要一个特定的组件即可在iframe.

但是有一个非常具体的问题,我什至还没有开始调试。

正如您从CodeSandbox 上这个最小的可重现示例中看到的那样,当将新元素添加到iframe中时,用户事件(即点击)开始被识别需要相当长的时间。(在我的场景中甚至更加明显,以至于完全无法使用)

有没有精通 Vue 的人至少了解为什么会发生这种情况,以及是否有办法防止它发生?

任何见解将不胜感激。谢谢。


*原因是我正在构建一个将侧边栏注入页面的浏览器扩展,并且我需要隔离 CSS,因为该扩展要在各种页面上使用,因此几乎不可能防止所有样式泄漏到注入侧边栏。

是的,避免使用iframeand using#myDiv{ all: unset }在某种程度上有效,但对于页面 CSS 中定义的一些非常具体的选择器会失败(并且完全不适用于input元素)。在我想要支持的所有页面上寻找它们很快就会变成一场噩梦。

标签: javascriptvue.jsiframedom-eventsvuejs3

解决方案


回答我自己的问题,因为没有人对此有所了解。然而,这并不能回答最初的问题,但我认为如果有人偶然发现这个问题,他们应该知道我是如何解决它的。

最后,我放弃了 iFrame 的想法,并使用Shadow DOM的概念来隔离页面的 CSS 和注入的扩展的 CSS。

尽管这种方法有其自身的警告*,但恕我直言,它优于使用 iframe。

*就像需要手动将自定义样式注入到 shadow-root 中一样。并且还需要将 shadow-root 元素存储在应用程序的所有部分都可以访问的地方(不是 Vuex,元素本身不能存储在那里)以使事情像工作一样。

这是我用来将侧边栏注入页面的代码片段:

// append a new node to the document body
let shadowHost = document.createElement("div");
document.body.appendChild(shadowHost);
    
// make it the root of our shadow DOM
let shadow = shadowHost.attachShadow({ mode: 'open'})

// create a new node for the sidebar
let sidebar = document.createElement("div");
sidebar.id = "my-sidebar";

// and also a style node into which we put all our custom css
const style = document.createElement('style');
// getPackedCss is my function that returns all the custom css as a string
style.textContent = getPackedCss();

// and append those to the shadow DOM
shadow.appendChild(style);
shadow.appendChild(sidebar);
    
// store the shadow root somewhere that we can access
// globally in order to select elements from it
staticStore.shadowRoot = shadow;

// create our vue app and mount it to the shadow DOM
const app = createApp(MyApp);
app.mount(sidebar);

如果你真的需要 Vue 3 和 iframe 来互相喜欢,我想你在这里是一个人。


推荐阅读