【问题标题】:How to run VueJS code only after Vue is fully loaded and initialized?如何仅在 Vue 完全加载和初始化后运行 VueJS 代码?
【发布时间】:2017-09-24 22:09:19
【问题描述】:

我正在开发一个 Vue 组件,该组件将通过 CMS 系统放置在多个网站上。我遇到的问题是,即使我的 js 脚本加载顺序正确,有时我也会收到此错误:

Uncaught ReferenceError: Vue is not defined
    at HTMLDocument.<anonymous>

Vue 是通过 cdn 加载的,它位于组件的代码之上。

所有的 Vue 代码都是这样运行的:

document.addEventListener("DOMContentLoaded", () => {
  // here is the Vue code
});

我什至在 DOMContentLoaded 事件中添加了一个 setTimeout(),但仍然没有成功。 window.onload = function() 在所有情况下都不起作用。我仍然不时收到该错误。 脚本加载到正文中。

您知道另一种方法是什么吗?我想确保在触发 Vue 代码的那一刻,Vue 已加载并准备好在页面上进行初始化。 谢谢!

【问题讨论】:

  • 尽量避免使用 CDN,这是一个异步进程,如果库更新,您的脚本可能会被破坏。
  • 作为解决方案,您可以检查间隔:'是 Vue 未定义吗?'

标签: javascript html vue.js


【解决方案1】:

使用 vue mounted() 在页面加载时运行任何代码,使用 updated() 在任何组件操作之后运行,因此完美的解决方案是结合 Roy j 和 vue lifecycle hooks

mounted() {
    window.addEventListener('load', () => {
         // run after everything is in-place
    })
},

// 99% using "mounted()" with the code above is enough, 
// but incase its not, you can also hook into "updated()"
//
// keep in mind that any code in here will re-run on each time the DOM change
updated() {
    // run something after dom has changed by vue
}

请注意,您可以省略 window.addEventListener(),它仍然可以工作,但如果您使用类似 jquery outerHeight(true) 之类的东西,它可能会丢失 + 最好在窗口事件中使用它以确保您获得正确的值.

更新 1:

除了window.addEventListener('load'),还有另一种方法是使用document.readyState,所以上面可以

mounted() {
  document.onreadystatechange = () => { 
    if (document.readyState == "complete") { 
        // run code here
    } 
  }
},

更新 2:

到目前为止,我发现的最可靠的方法是在 $nextTick 上使用 debounce,所以用法变成了

import debounce from 'lodash/debounce'

// bad
updated() {
    this.$nextTick(debounce(() => {
        console.log('test') // runs multiple times
    }, 250)) // increase to ur needs
}

// good
updated: debounce(function () {
    this.$nextTick(() => {
        console.log('test') // runs only once
    })
}, 250) // increase to ur needs

当使用 debounceupdated 时会变得很棘手,因此请务必继续测试它。

更新 3:

你也可以试试MutationObserver

【讨论】:

  • 鉴于这个问题是在 Vue 的上下文中提出的,这应该是公认的答案。
  • Vue.nextick 在这种情况下而不是 setTimeout。
  • @Johnson nexttick 并不总是按预期工作,也不会超时,因为 dom 可能需要更长的时间才能完成更新,遗憾的是,当 dom 完成更新时,vue 没有事件,所以它有点命中和错过跨度>
  • @ctf0 我没想到。你的回答最终对我没有帮助,因为我需要在 planner.vue 上进行 axios 调用来更新 vuex 状态,并且上面的代码可以工作,但只有一次,如果 dom 加载到特定的路由上使用 planner.vue,如果我加载主页然后转到 /app/planner 模板将不会加载,因为 dom 已经在主页中加载过一次。我最终不得不将整个 axios 请求移动到一个 Vuex 操作中,然后在创建 Vuex 实例后立即调度它。顺便说一句,这应该是公认的答案。大声笑
  • @AdrianoResende 添加了
【解决方案2】:

使用the load event 等待所有资源加载完毕:

<script>
  window.addEventListener("load", function(event) {
    // here is the Vue code
  });
</script>

Further explanation

DOMContentLoaded 是在解析 HTML 时触发的事件,并且 渲染并构造 DOM。它通常在 应用程序的生命周期。另一方面,load 仅在以下情况下被触发 所有资源(图像、样式表等)都从 网络和浏览器可用。

您也可以使用the load event for a specific script

【讨论】:

  • 我只是把console.log放在那些函数里,什么也没发生,我如何测试它是否有效
  • console.log 应该可以查看代码是否已运行。您还可以进入浏览器调试器并设置断点。也许你应该发布一个问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-12-17
  • 2015-01-18
相关资源
最近更新 更多