如何使用 Typescript 在 Vue 3.0 setup() 函数中使用 async/await

Posted

技术标签:

【中文标题】如何使用 Typescript 在 Vue 3.0 setup() 函数中使用 async/await【英文标题】:How can I use async/await in the Vue 3.0 setup() function using Typescript 【发布时间】:2021-01-14 22:01:39 【问题描述】:

(这个问题已经回答了 javascript,见下文,但这个问题是针对 TypeScript 的,它的行为不同)

我正在尝试使用打字稿在 Vue3.0 中使用异步功能。

没有 async,这段代码运行良好:

// file: components/HelloWorld.vue

<template>
  <div class="hello">
    <h1> msg </h1>
  </div>
</template>

<script lang="ts">
import defineComponent from 'vue'

export default defineComponent(
  name: 'HelloWorld',
  props: 
    msg: String,
  ,
  async setup()  // <-- this works without 'async'
    const test = 'test'

    // await doSomethingAsynchronous()

    return 
      test,
    
  ,
)
</script>

async setup() 组件“HelloWorld”从页面中消失,Firefox 控制台告诉我

"Uncaught (in promise) TypeError: node is null (runtime-dom.esm-bundler.js)"

当我将async setup() 更改为setup() 时,代码有效, 但随后我将无法在 setup 函数中使用 async/await。

所以我的问题: 如何使用 Typescript 在 setup() 函数中使用 async/await?

编辑:

这个问题的答案:why i got blank when use async setup() in Vue3 表明async setup() 确实适用于 JavaScript,所以我希望它也适用于 TypeScript。

【问题讨论】:

要使用async setup(),你需要使用,你可以google并阅读它的工作原理。 谢谢,我会在我再次尝试async setup() 时进行调查。 关于 它只能应用于子组件,因此您不能在具有异步设置的同一组件中使用 ,这意味着 App.vue(***组件)必须是同步的,有点烦人,但它就是这样工作的。 【参考方案1】:

尝试使用onMounted钩子来操作异步调用:

 setup() 
    const users = ref([]);
    onMounted(async () => 
      const res = await axios.get("https://jsonplaceholder.typicode.com/users");
      users.value = res.data;
      console.log(res);
    );

    return 
      users,
    ;
  ,

LIVE DEMO

【讨论】:

这确实有效。但我不想在开始异步调用之前等待组件挂载。 @HendrikJan 你可以使用 onBeforeMount 而不是 onMounted @HendrikJan 您甚至可以在 beforeCreate 生命周期挂钩之前开始异步调用,请参阅 here。【参考方案2】:

另一种方法:

 const users = ref([]);
 
 (async () => 
   const res = await axios.get("https://jsonplaceholder.typicode.com/users");
   users.value = res.data;
   console.log(res);
 )()

 return 
   users,
 

而且您不必等待它挂载,这类似于将 created() 与选项 API 一起使用。

注意:不要忘记始终使用分号“;”在函数语句之前,否则,JavaScript 会认为前面的语句应该返回一个函数,例如下面的代码会导致错误“ref([]) is not a function”:

const users = ref([]) // No semicolon here

(async () => 

防止这个错误的另一种方法是在函数定义的同一行始终使用分号,以下代码也可以:

;(async () => 

【讨论】:

干净多了!并且注意不要将执行括号放在分组括号内:你会得到一个 TS1128: Declaration or statement expected. 当您创建一个立即调用的函数时,您将线程分成两个并行运行。此答案将始终返回一个空用户,然后对其进行更新。您应该改用 suspense 和异步设置。除非你想要这种更新 UI 的错误体验。【参考方案3】:

另一种方法是使用承诺链,这样做的好处是代码甚至在 beforeCreate 生命周期钩子之前运行:

import  defineComponent, ref  from 'vue'
import  getData  from './api.js'

export default defineComponent(
  setup() 
    const users = ref([])

    getData().then(( data ) => (users.value = data))

    return 
      users,
    
  ,
)

【讨论】:

以上是关于如何使用 Typescript 在 Vue 3.0 setup() 函数中使用 async/await的主要内容,如果未能解决你的问题,请参考以下文章

Vuejs301- Vue 3.0前的 TypeScript 最佳入门实践

最新 Vue 3.0 源码开放了

如何在 TypeScript 3.0 中使用项目引用?

vue 3.0 封装 Toast 组件

快讯 | Vue 3.0 源码来了

Vue 3.0 源码发布,面试该怎么回答?