Vue.js 异步Vue生命周期

Vue.js 异步Vue生命周期,vue.js,Vue.js,我的Vue.js应用程序中存在以下情况: data() { return { data: [] } }, async created() { console.log('before async call') try { // async call ... console.log('after async call') this.data = // data from api call } catch (err) {

我的Vue.js应用程序中存在以下情况:

data() {
   return {
      data: []
   }
},

async created() {
   console.log('before async call')
   try {
      // async call ...
      console.log('after async call')
      this.data = // data from api call
   } catch (err) {
      // handle err
   }
},

mounted() {
   console.log('mounted')
   init(this.data)
}
当我运行代码时,我得到:

before async call
mounted
after async call

因此,将使用空数组而不是API调用中的数据调用挂载中的类构造函数init方法。我想要的是同步执行,在数据可用之前不执行挂载。我知道上面的问题是当包含异步代码时Vue如何执行生命周期,但是您如何解决这些问题呢?

如果我是您,我会将所有逻辑放在挂载或创建的钩子中。如果出于某种原因,您需要等到挂载后代码才能工作,请获取数据并在挂载中初始化它:

async mounted() {
   try {
      // async call ...
      console.log('after async call')
      this.data = await // data from api call
      init(this.data)
   } catch (err) {
      // handle err
   }
}
在性能方面,将代码划分为创建代码和装载代码几乎没有任何好处

不过,如果出于某种原因确实需要将它们放在不同的挂钩中,您可以将数据存储在承诺中:

async created() {
   console.log('before async call')
   try {
      // async call ...
      console.log('after async call')
      this.data = fetch('whatever') // now this.data is a promise
   } catch (err) {
      // handle err
   }
},

async mounted() {
   console.log('mounted')
   init(await this.data)
}
这应该行得通,但我认为不值得这么麻烦


作为对可能阅读本文的人的澄清:您可以在vue生命周期挂钩中使用async/await,以便在其中编写代码以等待承诺等。但是,这不会使vue真正等待生命周期本身:因此您可以在创建异步代码之前运行装入的代码。Vue不等待异步生命周期这一事实并不意味着在其中放置异步/等待代码是不好的。

如果我是你,我会将所有逻辑放在挂载或创建的钩子中。如果出于某种原因,您需要等到挂载后代码才能工作,请获取数据并在挂载中初始化它:

async mounted() {
   try {
      // async call ...
      console.log('after async call')
      this.data = await // data from api call
      init(this.data)
   } catch (err) {
      // handle err
   }
}
在性能方面,将代码划分为创建代码和装载代码几乎没有任何好处

不过,如果出于某种原因确实需要将它们放在不同的挂钩中,您可以将数据存储在承诺中:

async created() {
   console.log('before async call')
   try {
      // async call ...
      console.log('after async call')
      this.data = fetch('whatever') // now this.data is a promise
   } catch (err) {
      // handle err
   }
},

async mounted() {
   console.log('mounted')
   init(await this.data)
}
这应该行得通,但我认为不值得这么麻烦

作为对可能阅读本文的人的澄清:您可以在vue生命周期挂钩中使用async/await,以便在其中编写代码以等待承诺等。但是,这不会使vue真正等待生命周期本身:因此您可以在创建异步代码之前运行装入的代码。Vue不等待异步生命周期并不意味着在其中放置异步/等待代码是不好的。Vue中的异步生命周期是一种误导性语法

每个Vue生命周期都只是一个触发器,用于运行您在特定时间放入其中的任何代码

但是Vue不会等到承诺解决并保留与组件生命周期相关的所有其他问题,直到它发生。实际上,您所做的只是延迟在生命周期中放置的代码的执行,直到某个承诺得到解决

为了让您更好地理解正在发生的事情,以下语法是等效的:

async created() {
  const data = await fetchSomeData(); 
  // rest of code depending on `data`
}
created() {
  fetchSomeData().then(data => {
    // rest of code depending on `data`
  });
}
等价物:

async created() {
  const data = await fetchSomeData(); 
  // rest of code depending on `data`
}
created() {
  fetchSomeData().then(data => {
    // rest of code depending on `data`
  });
}
因为异步生命周期是一种误导性的语法,所以在大型团队开发的应用程序中通常不鼓励使用它,而支持.then语法。这是为了避免在代码实际运行时由于误解而产生的小错误。例如,如果新开发人员将一些代码放入异步钩子中,而没有仔细查看钩子中的其余代码,那么代码可能会比预期的运行得晚,除非放在任何等待之前

要修复您试图修复的任何错误,只需将在实际数据解析为if-inside组件或v-if-inside模板之前无法呈现的内容包装起来即可

典型用法示例:

computed: {
  someComputed() {
    if (this.data.length) {
      // returned when data has length
      return something
    }
    // returned when data has no length
    return somethingElse
  }
}
或:

注意:上面计算的属性将自动对数据长度的变化作出反应,无需监视,因为只要内部反应引用的值发生变化,计算属性就会重新运行。正如您所料,他们会根据自己的情况重新计算/重新提交任何内容。同样的道理也适用于中国。在内部,它们都使用所谓的Vue注入和反应性。

Vue中的异步生命周期是一种误导性语法

每个Vue生命周期都只是一个触发器,用于运行您在特定时间放入其中的任何代码

但是Vue不会等到承诺解决并保留与组件生命周期相关的所有其他问题,直到它发生。实际上,您所做的只是延迟在生命周期中放置的代码的执行,直到某个承诺得到解决

为了让您更好地理解正在发生的事情,以下语法是等效的:

async created() {
  const data = await fetchSomeData(); 
  // rest of code depending on `data`
}
created() {
  fetchSomeData().then(data => {
    // rest of code depending on `data`
  });
}
等价物:

async created() {
  const data = await fetchSomeData(); 
  // rest of code depending on `data`
}
created() {
  fetchSomeData().then(data => {
    // rest of code depending on `data`
  });
}
因为异步生命周期是一种误导性的语法,所以在大型团队开发的应用程序中通常不鼓励使用它,而支持.then语法。这是为了避免在代码实际运行时由于误解而产生的小错误。例如,如果新开发人员将一些代码放入异步钩子中,而没有仔细查看钩子中的其余代码,那么代码可能会比预期的运行得晚,除非放在任何等待之前

要修复您试图修复的任何错误,只需将在实际数据解析为if-inside组件或 v-if内部模板

典型用法示例:

computed: {
  someComputed() {
    if (this.data.length) {
      // returned when data has length
      return something
    }
    // returned when data has no length
    return somethingElse
  }
}
或:

注意:上面计算的属性将自动对数据长度的变化作出反应,无需监视,因为只要内部反应引用的值发生变化,计算属性就会重新运行。正如您所料,他们会根据自己的情况重新计算/重新提交任何内容。同样的道理也适用于中国。在内部,它们都使用所谓的Vue注入和反应