Skip to content
页面概要

asyncData 方法

midway-vue3-ssr 扩展了 Vue.js,增加了一个叫 asyncData 的方法,使得我们可以在设置组件的数据之前能获取或处理数据。

说明

asyncData方法会在组件每次加载之前被调用。它可以在服务端或路由更新之前被调用。在这个方法被调用的时候,第一个参数被设定为 storeroute、router 和 ctx(服务端存在)的集合IAsyncDataContext类型,你可以利用 asyncData方法来获取数据。

类型

import { Context } from '@midwayjs/koa';
import { RouteLocationNormalizedLoaded, Router } from 'vue-router';
import { Pinia } from 'pinia';

export interface IAsyncDataContext {
  route: RouteLocationNormalizedLoaded;
  store: Pinia;
  router: Router;
  ctx?: Context; // 在服务端运行时存在
}
declare module 'vue' {
  interface ComponentCustomOptions {
    asyncData?(context: IAsyncDataContext): Promise<any>;
  }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

使用

async





 
 
 
 



<script lang="ts">
import { defineComponent} from 'vue'
import { useAboutStore, IAboutState } from "./store";
export default defineComponent({
  async asyncData({store, route}) {
    const aboutStore = useAboutStore(store);
    await aboutStore.getList({current: Number(route.query.page || 1)});
  }
})
</script>
1
2
3
4
5
6
7
8
9
10

数据展示





 






 
 
 
 
 
 
 
 
 





<script lang="ts" setup>
import { useAboutStore, IAboutState } from "./store";
// 读取数据
const aboutStore = useAboutStore();
const tableData = computed<IAboutState>(()=>aboutStore.$state);
</script>
<template>
  <div class="about">
    <h1>This is an about page</h1>
    <div class="box">
      <ul v-loading="tableData.loading">
        <li v-for="item in tableData.list">

          <div>
            <router-link :to="{ path: '/detail', query: { id: item.id }}">
              {{item.title}}
            </router-link>
            <span>{{item.addtime}}</span>
          </div>
        </li>
      </ul>
    </div>
  </div>
</template>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

监听 query 参数改变

默认情况下,query 的改变不会调用 asyncData 方法。如果需要,可以监听这个行为。例如,在构建分页组件时,您可以设置 watch 监听参数。如下样列:


















 
 
 
 
 
 
 
 
 

















































<script lang="ts">
import { defineComponent, computed, watch } from 'vue'
import { useRoute } from "vue-router"
import Pagination from "@/components/Pagination/base.vue";
import { useAboutStore, IAboutState } from "./store";
export default defineComponent({
  async asyncData({store, route}) {
    const aboutStore = useAboutStore(store);
    await aboutStore.getList({current: Number(route.query.page || 1)});
  }
})
</script>
<script lang="ts" setup>
// 读取数据
const aboutStore = useAboutStore();
const tableData = computed<IAboutState>(()=>aboutStore.$state);

const route = useRoute();
const page = computed(()=>route.query.page);

watch(page,()=> {
  if(route.path !== '/about') {
    return;
  }
 aboutStore.getList({current: Number(page.value || 1)});
})
</script>
<template>
  <div class="about">
    <h1>This is an about page</h1>
    <div class="box">
      <ul v-loading="tableData.loading">
        <li v-for="item in tableData.list">

          <div>
            <router-link :to="{ path: '/detail', query: { id: item.id }}">
              {{item.title}}
            </router-link>
            <span>{{item.addtime}}</span>
          </div>
        
        </li>
      </ul>
      <div>
        <pagination :total="tableData.pagination.total" :current-page="tableData.pagination.current" page-url="/about?page={page}"></pagination>
      </div>
    </div>
  </div>
</template>
<style lang="scss" scoped>
.box {
  box-sizing: border-box;
  min-width: 200px;
  max-width: 980px;
  margin: 0 auto;
  padding: 45px;
  text-align: left;
  ul {
    li {
      padding: 5px 0;
     div {
      display: flex;
      justify-content: space-between;
     }
    }
  }
}
@media (max-width: 767px) {
  .box {
    padding: 15px;
  }
}
</style>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74

Released under the MIT License.