iframe 加载事件触发两次

Iframe load event fires twice

绑定到 (@load="myFunction") 的函数在创建 iframe 时触发一次,在实际加载时触发一次。

为什么创建 iframe 时会触发,如何避免?

<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>

这似乎是一个网络工具包问题,触发两次 ( safari/chrome ),因为它在添加到 DOM 时触发(v-if 在父级上)并且在加载内容时触发。将 .once 修饰符添加到 @load.once="myFunction()"

可能会有所帮助

我们从您的 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 那里得知。我们希望它发生在 iframe 添加到 DOM 之后,但在它有机会加载之前,所以我们将使用 updated 钩子。

我在我的任何浏览器中都没有遇到这个问题,所以遗憾的是我无法真正为您测试。自己测试一下,看看是否有类似这样的方法可以解决问题:

<template>
  <label for="show">Show iFrame</label>
  <input id="show" type="checkbox" v-model="webviewOpen">
  <div v-if="webviewOpen">
    <iframe
      src="https://motherfuckingwebsite.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>

正如@tao 所建议的那样,其他东西正在干扰,即 Nuxt Lazy Load 包。因此,如果有人使用这个包并发现 iframe onload 事件神秘地触发了两次并找到了这个线程:

modules 部分中导入包时,在 nuxt.config.js 中添加 iframes: false。问题已解决!