【问题标题】:Initialize Vue.prototype before component loads在组件加载之前初始化 Vue.prototype
【发布时间】:2020-03-14 23:26:55
【问题描述】:

我的代码使用 Vuejs 中的插件功能来定义全局共享变量。

Vue.use(shared)

shared 定义为:-

export const shared = {
  config: getAppConfig()
}
shared.install = function() {
  Object.defineProperty(Vue.prototype, '$shared', {
    get() {
      return shared
    }
  })
}

function getAppConfig() {
  var api = getAPIURL()
  return axios.get("https://url/get_config")
  .then(response => {
    return response.data
  }
}

我的问题是,在我的组件中,如果我使用这个变量this.$shared.config,我会得到undefined

查看控制台窗口和调试语句,我的组件代码在插件有时间到this.$shared.config之前执行。

我是 javascript+Vuejs 的新手,但是当我研究这个错误时,它与 axios 异步有关,所以我决定返回 promise 并使用 await。

function getAppConfig() {
  var api = getAPIURL()
  return axios.get("https://url/get_config")
}

但是,在我的 shared.install 函数中,我尝试这样做:-

shared.install = function() {
  let config = await shared.config

我收到错误:Syntax Error: await is a reserved word

由于我是新手,我在如何使这段代码同步方面似乎犯了一个基本错误。解决此问题的正确方法是什么?

【问题讨论】:

  • 如果应用配置如此重要,也许您应该延迟实例化您的 VueJS 应用,直到您收到来自端点的响应?
  • function getAppConfig 不返回任何内容,因此结果为undefined - 问题二,await 只能用于async 的函数中...
  • 问题三我应该如何使这段代码同步 - 你不能。异步结果不能制作同步,除非您将检索结果的方式更改为同步 - 并且不推荐使用同步 XMLHttpRequest 并导致糟糕的用户体验
  • 取决于您的使用情况 - 即您如何在组件中使用这些数据,npmjs.com/package/vue-async-computed 可能会有所帮助
  • @JaromandaX 我有一个用例,我的应用配置只能通过 HTTP 请求获取。安装新插件是唯一的方法吗?

标签: javascript vue.js promise


【解决方案1】:

Vue 并不特别支持异步初始化的插件。

如果组件将在Vue.use(shared) 之后立即实例化,则$shared 将不可用。应该存在可以链接的承诺,例如:

install() {
  Vue.sharedPromise = getAppConfig();
  Vue.sharedPromise.then(config => {
    Vue.prototype.$shared = config
  });
}

Vue.use(shared);
Vue.sharedPromise.then(() => {
  // $shared is available, mount app
});

由于没有必要将异步操作推送到插件,因此可以将其保留在外部:

install(Vue, { config }) {
  Vue.prototype.$shared = config;
}

getAppConfig().then(config => {
  Vue.use(shared, { config });
  // $shared is available, mount app
});

【讨论】:

  • 感谢您的回答。我打算以这种方式实现。感谢您提出推荐的方法并解释为什么它不能以这种方式工作。如果非常不鼓励这种方法,您能否说明一下? sprunge.us/wWz1LF
  • 确实如此。 $shared 在安装组件时将不可用,并且您不知道它何时可用,因为它不是响应式的。它工作的唯一方法是使用巨大的 setTimeout 并希望它在延迟后可用。
  • 如果你出于某种原因进行异步初始化,至少要确保你公开了一个可以链接在依赖于初始化的地方的 Promise。如果你有 initPromise(在 Vue.prototype 上导入或公开),你需要在每个相关的地方做async mounted() { await initPromise; ... }。参见 auth0ClientPromise 这里例如 stackoverflow.com/a/60713249/3731501 ,这是一个类似于你的情况,但 OP 选择在启动后完成 init 因为它对于身份验证令牌是可以接受的(但它可能不适用于像 $shared 这样的应用程序范围的配置)。
  • 感谢您的帮助
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-07-01
  • 1970-01-01
  • 2018-09-05
  • 2019-12-07
相关资源
最近更新 更多