清理mount() - 附加脚本在Vue组件中的destroyed()回调中

时间:2018-02-20 23:21:51

标签: html vue.js vuejs2 vue-component script-tag

我正在以编程方式将必要的脚本添加到我的一些Vue组件中,如下所示:

mounted() {
    const
        googleRecaptchaScript = document.createElement('script'),
        recaptchaURL = 'https://www.google.com/recaptcha/api.js';
    googleRecaptchaScript.setAttribute('src', recaptchaURL);
    googleRecaptchaScript.setAttribute('id', 'grecaptchascript');
    document.head.appendChild(googleRecaptchaScript);
},

现在,我注意到如果我离开组件并返回到它,而不刷新页面批发,那么Vue将开始加载我在mounted()调用中附加的内容的重复副本。所以我想按照以下方式清理它们:

beforeDestroy() {
    const gsc = document.getElementById('grecaptchascript');
    gsc.parentElement.removeChild(gsc);
},

然而,似乎该脚本的id从未设置过,因此清理步骤无声地失败。

我完全错了吗?这样做是一个更好的模式吗?如果没有,为什么<script>我的id设置不正常?

脚注:我知道在这里使用id是有问题的,因为我们讨论的是重复元素。我稍后会改变它。如果有帮助,请考虑通过任意属性进行选择的一般情况。我尝试了其他属性但没有成功。

2 个答案:

答案 0 :(得分:1)

我认为没有必要进行这样的清理:在加载脚本之后,所有函数和变量的定义都属于全局范围,卸载脚本后它们不会被删除。

您需要检查脚本是否已加载,并且不要加载多次:

mounted() {
  const gsc = document.getElementById('grecaptchascript');
  if (!gsc) {
    const
      googleRecaptchaScript = document.createElement('script'),
      recaptchaURL = 'https://www.google.com/recaptcha/api.js';
    googleRecaptchaScript.setAttribute('src', recaptchaURL);
    googleRecaptchaScript.setAttribute('id', 'grecaptchascript');
    document.head.appendChild(googleRecaptchaScript);
  }
}

答案 1 :(得分:0)

我不确定问题到底是什么,但是为了将来参考,这个解决方案有效并且对我的情况看起来相当不错,因为它选择了src的{​​{1}}属性的前缀:

mounted() {
    const
        googleRecaptchaScript = document.createElement('script'),
        recaptchaURL = `https://www.google.com/recaptcha/api.js?hl=${this.$i18n.locale}`;
    googleRecaptchaScript.setAttribute('src', recaptchaURL);
    document.head.appendChild(googleRecaptchaScript);
},
beforeDestroy() {
    const recaptchaScripts = document.querySelectorAll('script[src^="https://www.google.com/recaptcha/api.js"]');
    for (let i = 0; i < recaptchaScripts.length; i += 1) {
        recaptchaScripts[i].parentElement.removeChild(recaptchaScripts[i]);
    }
},

我很确定id也会很好,我只是愚蠢。如果有人有更好的解决方案,我仍然会感兴趣,因为“手动”(以编程方式)从页面中选择和删除元素似乎有点脏。