drake035
drake035

Reputation: 2897

Iframe load event fires twice

The function bound to (@load="myFunction") fires once when the iframe is created and once when it's actually loaded.

Why does it fire when the iframe is created, and how to avoid it?

<template>
  <transition name="modal">
    <div v-if="webviewOpen">
      <transition name="content" appear>
        <div v-if="webviewOpen">
            <transition name="iframe">
            <iframe
              v-show="showIframe"
              :src="webviewUrl"
              @load="iframeIsLoaded"
            />
          </transition>
        </div>
      </transition>
    </div>
  </transition>
</template>

<script>
import { mapState } from 'vuex'

export default {
  data () {
    return {
      showIframe: false
    }
  },
  computed: {
    ...mapState({
      webviewOpen: state => state.webview.open,
      webviewUrl: state => state.webview.url
    })
  },
  watch: {
    webviewOpen () {
      setTimeout(() => {
        this.showIframe = true
      }, 1000)
    }
  },
  methods: {
    iframeIsLoaded () {
      console.log('iframe loaded')
    }
  }
}
</script>

Upvotes: 0

Views: 9785

Answers (3)

matthew-e-brown
matthew-e-brown

Reputation: 3087

We know from your linked answer that Chrome shows this issue unless you attach the listener after the iframe is appended to the DOM. To do this, we could take advantage of Vue's lifecycle hooks. We want it to happen after the iframe is added to the DOM, but before it has a chance to load, so we'll use the updated hook.

I don't experience the problem in any of my browsers, so I unfortunately can't really test it for you. Test for yourself and see if something like this fixes it for you:

<template>
  <label for="show">Show iFrame</label>
  <input id="show" type="checkbox" v-model="webviewOpen">
  <div v-if="webviewOpen">
    <iframe
      src="https://testwebsite.com/"
      @load="iframeLoadHelper"
      frameborder="0"
    ></iframe>
  </div>
</template>

<script>
export default {
  name: 'App',
  data() {
    return {
      webviewOpen: false,
      iframeReady: false
    };
  },
  methods: {
    // Helper method, just to keep 'if' outside of the logic of your potentially
    // complex @load method
    iframeLoadHelper() {
      if (this.iframeReady) return this.iframeLoaded();
      else return; // do nothing
    },
    // The real load method
    iframeLoaded() {
      console.log('iframe loaded');
    }
  },
  updated() {
    console.log('changing ready-state');
    this.iframeReady = this.webviewOpen;
  }
};
</script>

<style>
:root { font-family: sans-serif; }
</style>

Upvotes: 1

drake035
drake035

Reputation: 2897

As @tao suggested something else was interefering, namely Nuxt Lazy Load package. So if anyone uses this package AND finds out iframes onload event mysteriously fires twice AND finds this thread:

Add iframes: false in your nuxt.config.js when importing the package inside the modules section. Problem solved!

Upvotes: 2

HugoDos
HugoDos

Reputation: 329

It seems it may be a web kit issue with firing twice ( safari/chrome ) as it fires when added to DOM (v-if on parent) and when the content is loaded. It may help to add .once modifier to the @load.once="myFunction()"

Upvotes: 3

Related Questions