Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

click event is registered delayed on components opened in new browser windows #3933

danielSt-dev opened this issue Jun 10, 2021 · 9 comments
🐞 bug Something isn't working 🔩 p2-edge-case


Copy link

danielSt-dev commented Jun 10, 2021



Reproduction link

Steps to reproduce

  1. open child window with a click on "open,close window" for the first time and wait 3 seconds
  2. click on message --> nothing happens
  3. wait 3 seconds and click again --> nothing happens
  4. wait another 15 seconds and click again --> alert message in "main" window appears (chrome: if devtools are closed, a dot on the tab of main window notifies you, that an alert is there)

So you see, there is a relatively long time until the click handler will be registered (about 15-20 seconds)

Now close the window with a click on "open,close window" in main window.

If you repeat the above steps, the click handler will only be called after a few minutes (1-2 minutes; if it won't work, leave it open and try it after 5-10 minutes).
With every close/open new window the time increases.
Important: Do not click too often after opening the window! It seems that the click eventhandler never gets registered if you click too often.

Info: firefox appears to be faster than chrome. After repeating this 4 times firefox needs about 3 minute that the click event is handled. chrome much more.

What is expected?

click events should be fired/registered immediately

What is actually happening?

it seems the click event will be registered delayed.

I found have a problem with click events on components, that are opened in a new browser window with vue 3.
I open a vue 3 component in a new window like the following code (copied and customized from

    <teleport to="body">
        <div v-if="open" v-show="windowLoaded" ref="teleportingContent">
methods: {
  openPortal() {
    this.windowRef ='', '', '');
    this.windowRef.document.body.innerHTML = '';
    const app = document.createElement('div'); = 'app';

With this code the slot component will be attached to the DOM of the new opened window. This works and the vue objects/props are reactive in the new window.

The problem is if there is a click-eventhandler on an element, which is attached to DOM of the new window. It seems that the click event is registered delayed.

If the window is closed/opened multiple times, the time of the click registration increases every time.

I want to be able to "dock off" some content of the main window to a new window (e. g. from a video conference push two video participants to new windows; move a component to a new window for comparing content in two screens).

Copy link

lidlanca commented Jun 11, 2021

bug related to fix made for vuejs/vue#6566

The issue is, that for browsers where the event uses the hi-res timestamp
The child window time resets/start from 0, when the new window is opened, creating the discrepancy
events triggered in the child will have a lower timestamp than the parent window.

The event handler is invoked only when the child window internal time catch up to the time the element was created in the parent.

Copy link

same story for elements moved to an iframe.

@yyx990803 yyx990803 added 🐞 bug Something isn't working 🔨 p3-minor-bug Priority 3: this fixes a bug, but is an edge case that only affects very specific usage. labels Jun 22, 2021
@yyx990803 yyx990803 added 🔩 p2-edge-case and removed 🔨 p3-minor-bug Priority 3: this fixes a bug, but is an edge case that only affects very specific usage. labels Jul 21, 2021
Copy link

AurelieV commented Oct 8, 2021

For information, this is how we temporaly fix it for our usecase (App which load components inside iframe)

iframe.onload = () => { =

Tested only on Chrome, this is a way to resynchronise the timestamps used by Vue

Copy link

danielSt-dev commented Oct 13, 2021

@AurelieV thanks for your workaround! It works great!
The only thing I had to do is wrapping the assignment in a new function: = () => { return; };
Otherwise the will not be overridden.

Copy link

when I use teleport whose to is shadow root, there is also a relatively long time until the click handler will be registered (about 5 seconds)

Copy link

This seems related to #2513.

Copy link

danielSt-dev commented Jun 14, 2022

we updated our app to vue 3.2.37 and the workaround didn't work anymore.

It is because of merge #5944 (vue version 3.2.36). the call to through a function is replaced by a direct function assignment, so we can not override the anymore.

Current solution is downgrade to vue 3.2.35

Copy link

lidlanca commented Jun 16, 2022

another workaround

      // Skip timestamp check workaround.
      // Code must be called before vue runtime is imported/evaluated.
       const ffMatch = navigator.userAgent.match(/firefox\/(\d+)/i);
       skipTimestampCheck2 = !!(ffMatch && Number(ffMatch[1]) <= 53);

      let ua = window.navigator.userAgent;
      Object.defineProperty(window.navigator, 'userAgent', {
        get: () => {
          let s = new String(ua); 
          s.match = function (re) {
            // only care about this particualr match call.
            if (re.toString() === '/firefox\\/(\\d+)/i') {
              return [, 53];
            return ua.match(re);
          return s;
      // if we don't mind mutating userAgent, shorter version
      // Object.defineProperty(window.navigator,'userAgent',{get:()=>'firefox/53'})

related issue: #2513

Copy link

I encounter the same bug in Chrome.
I have a main VueJS app that load, one by one, multiple apps in an iframe.

All works perfectly, except the events in iframe apps. At the first load, the events are fired with a little delay, and as navigation go, the delay increase and the apps become unusable.

Thanks @AurelieV , I have begun to understand with your comment where the problem originated.

Unfortunately your solution was not enough for me :

iframe.onload = () => { = }

After several hours of research, i found that the event.timeStamp of each events was the key. It must be relative to, that was not the case for me, even if i replace the main by the one in the iframe.

Here the solution thats works for me :

iframe.onload = () => { = () =>;
   iframe.contentWindow.addEventListener('click', function(e) {
   	Object.defineProperty(e, "timeStamp", { 
   		get: () =>; 
   }, true);

This will make the click event works as soon as the application is mounted.

For all events, a little loop over onXXX properties could do the trick.

Here the final solution (all events type) :

const handler = (e) => {
    Object.defineProperty(e, "timeStamp", { get: () => })
const events = Object.keys(window).filter(name => name.substring(0, 2) == 'on').map(name => name.substring(2));
events.forEach((name) => iframe.contentWindow.addEventListener(name, handler, true));

Hope it will help someone ;-)

chrislone pushed a commit to chrislone/core that referenced this issue Feb 4, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
🐞 bug Something isn't working 🔩 p2-edge-case
None yet

No branches or pull requests

7 participants