在iframe中的Vue 3实例中延迟注册事件侦听器 [英] Delayed registration of event listeners in a Vue 3 instance inside an iframe

查看:79
本文介绍了在iframe中的Vue 3实例中延迟注册事件侦听器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

出于非常特定的原因*,我需要一个Vue实例在 iframe 中运行.在 Vue论坛上的该主题上,我设法做到了,然后进行了调整支持Vue 3并删除插槽的代码,因为我只需要一个特定的组件即可在 iframe 中运行.

For a very specific reason*, I need a Vue instance to run inside an iframe. I managed to do that following this thread on Vue forum, and tweaking the code to support Vue 3 and removing the slot, because I only need a specific component to run inside an iframe.

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

But there is a very specific problem that I haven't even managed to start debugging.

您可以从此 ="a href =" https://codesandbox.io/s/vue-iframe-problem-qroht?file=/src/App.vue"rel =" nofollow noreferrer中看到>> CodeSandbox上的最小可复制示例 ,当在 iframe 中添加新元素时,用户事件(即点击)开始花费大量时间公认的.(在我的场景中甚至更明显,以至于完全无法使用)

As you can see from this minimal reproducible example on CodeSandbox, when a new element is added into the iframe, it takes a considerable amount of time for the user events (namely clicks) to start getting recognised. (it is even more pronounced in my scenario, to the point of being completely unusable)

任何精通Vue的人是否至少了解这种情况的发生原因以及是否有办法防止这种情况的发生?

Does anyone who is well-versed in Vue at least understand why this is happening and if there is a way to prevent it from happening?

任何见识将不胜感激.谢谢.

Any insight would be much appreciated. Thanks.

*原因是我正在构建一个向页面注入侧栏的浏览器扩展,并且我需要隔离CS​​S,因为该扩展将用于各种页面,因此几乎不可能阻止所有样式泄漏到注入的侧边栏中.

*the reason being that I am building a browser extension that injects a sidebar into the page and I need to isolate the CSS, because the extension is to be used on various pages, so it is nearly impossible to prevent all stlyes from leaking into the injected sidebar.

是的,避免使用 iframe 并使用 #myDiv {all:unset} 可以在某种程度上起作用,但对于页面CSS中定义的某些非常具体的选择器则无效(而完全不适用于 input 元素).在我要支持的所有页面上寻找它们会很快成为一场噩梦.

Yes, avoiding an iframe and using #myDiv{ all: unset } instead works to some extent, but fails for some very specific selectors defined in the page's CSS (and outright does not work for input elements). Hunting for them on all pages that I want to support would quickly become a nightmare.

推荐答案

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

Answering my own question, since no one has shed any light on this. This does not, hovewer, answer the original question, but I figured that should anyone stumble upon this problem, they should know how I managed to solve it.

最后,我放弃了iFrame的想法,并使用了

In the end, I ditched the idea of an iFrame and used the concept of Shadow DOM to isolate the page's CSS and the injected extension's CSS from each other.

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

Although this approach comes with its own caveats*, it is IMHO superior to using iframes.

*就像需要将自定义样式手动插入到阴影根目录中一样.并且还需要将shadow-root元素存储在应用程序的所有部分都可以访问的位置(不是Vuex,该元素本身不能存储在此处),以使工作正常进行.

*like the need to manually inject custom styles into the shadow-root. And also the need to store the shadow-root element somewhere that all parts of your application can access (NOT Vuex, the element itself cannot be stored there) in order to make things like work.

这是我用来将侧栏注入到页面中的一小段代码:

Here is a snippet of code I used to inject the sidebar into the page:

// 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彼此喜欢,我想您就在这里了.


If you reeeally need Vue 3 and an iframe to like each other, I guess you are on your own here.

这篇关于在iframe中的Vue 3实例中延迟注册事件侦听器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆