如何使用 Typescript 在 Vue 3.0 setup() 函数中使用 async/await
How can I use async/await in the Vue 3.0 setup() function using Typescript
(此问题已针对 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()
时,代码有效,
但是我将无法在设置函数中使用 async/await。
所以我的问题是:
如何使用 Typescript 在 setup() 函数中使用 async/await?
编辑:
这个问题的答案: 表明 async setup()
确实适用于 JavaScript,所以我希望它也适用于 TypeScript。
尝试使用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,
};
},
但是最好的方法是在子组件中使用async setup
并用父组件中的Suspense
组件包装该组件:
UserList.vue
<script lang="ts">
import { defineComponent } from "vue";
export default defineComponent({
async setup() {
//get users from jsonplacerholder using await fetch api
const users = await fetch("https://jsonplaceholder.typicode.com/users").then(res => res.json());
return {
users
}
}
})
</script>
<template>
<div>
<!-- list users -->
<ul>
<li v-for="user in users">{{ user.name }}</li>
</ul>
</div>
</template>
父组件:
<script lang="ts">
import UserList from "../components/tmp/UserList.vue";
...
</script>
<div>
<!-- Suspense component to show users -->
<Suspense>
<template #fallback>
<div>loading</div>
</template>
<UserList />
</Suspense>
</div>
另一种方法:
const users = ref([]);
(async () => {
const res = await axios.get("https://jsonplaceholder.typicode.com/users");
users.value = res.data;
console.log(res);
})()
return {
users,
}
而且您不必等待它挂载,这类似于使用带有选项 API.
的 created()
注意:不要忘记始终使用分号“;”在函数语句之前,否则,JavaScript 会认为前面的语句应该是 return 一个函数,例如下面的代码,会导致错误 "ref([]) is not a function ":
const users = ref([]) // No semicolon here
(async () => {
另一种防止此错误的方法是在函数定义的同一行始终使用分号,以下代码也有效:
;(async () => {
另一种方法是使用承诺链,这样做的好处是代码 运行 甚至在 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,
}
},
})
(此问题已针对 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()
时,代码有效,
但是我将无法在设置函数中使用 async/await。
所以我的问题是: 如何使用 Typescript 在 setup() 函数中使用 async/await?
编辑:
这个问题的答案:async setup()
确实适用于 JavaScript,所以我希望它也适用于 TypeScript。
尝试使用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,
};
},
但是最好的方法是在子组件中使用async setup
并用父组件中的Suspense
组件包装该组件:
UserList.vue
<script lang="ts">
import { defineComponent } from "vue";
export default defineComponent({
async setup() {
//get users from jsonplacerholder using await fetch api
const users = await fetch("https://jsonplaceholder.typicode.com/users").then(res => res.json());
return {
users
}
}
})
</script>
<template>
<div>
<!-- list users -->
<ul>
<li v-for="user in users">{{ user.name }}</li>
</ul>
</div>
</template>
父组件:
<script lang="ts">
import UserList from "../components/tmp/UserList.vue";
...
</script>
<div>
<!-- Suspense component to show users -->
<Suspense>
<template #fallback>
<div>loading</div>
</template>
<UserList />
</Suspense>
</div>
另一种方法:
const users = ref([]);
(async () => {
const res = await axios.get("https://jsonplaceholder.typicode.com/users");
users.value = res.data;
console.log(res);
})()
return {
users,
}
而且您不必等待它挂载,这类似于使用带有选项 API.
的 created()注意:不要忘记始终使用分号“;”在函数语句之前,否则,JavaScript 会认为前面的语句应该是 return 一个函数,例如下面的代码,会导致错误 "ref([]) is not a function ":
const users = ref([]) // No semicolon here
(async () => {
另一种防止此错误的方法是在函数定义的同一行始终使用分号,以下代码也有效:
;(async () => {
另一种方法是使用承诺链,这样做的好处是代码 运行 甚至在 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,
}
},
})