Nuxt.js의 asyncData를 Composition API로

마지막 기사 다음에 Nuxt.js 주위의 실험 중입니다.

vue3에서 정식 도입 예정인 composition-api를 Nuxt.js에서 시도했습니다.

nuxtjs/composition-api 설치



Nuxt.js 용 composition-api를 설치하십시오.
※ 9/3 시점에서 v0.12.2 라고 버젼도 낮아 앞으로 여러가지 바뀌어 갈 가능성이 있으므로 주의입니다.
$ npm install @nuxtjs/composition-api --save

nuxt.config.js에 설정 추가



buildModules 옵션에 추가

nuxt.config.js
{
  buildModules: [
    '@nuxtjs/composition-api'
  ]
}

jest에 대한 설정 추가



※ 이 기사에서는, jest에 대해서는 쓰지 않습니다만, 향후 쓰므로 일단.

jest.config.js
moduleNameMapper: {
  '@nuxtjs/composition-api': '@nuxtjs/composition-api/lib/cjs/entrypoint.js',
},

composition-api 형식으로 기존 구성 요소를 다시 작성



Nuxt.js + buefy로 설치한 경우
기본적으로 작성된 components/Card.vue를 다음과 같이 다시 작성합니다.

components/Card.vue
<template>
  <div class="column">
    <div class="card">
      <header class="card-header">
        <p class="card-header-title has-text-grey">
          {{ state.card.title }}
        </p>
      </header>
      <div class="card-content">
        <div class="content has-text-centered">
          <b-icon :icon="state.card.icon" size="is-large" type="is-primary" />
        </div>
      </div>
      <footer class="card-footer">
        <div class="card-footer-item">
          <span v-html="state.card.content"></span>
        </div>
      </footer>
    </div>
  </div>
</template>

<script lang="ts">
import { computed, defineComponent, reactive } from '@nuxtjs/composition-api'

export default defineComponent({
  props: {
    title: {
      type: String,
      required: true,
    },
    icon: {
      type: String,
      required: true,
    },
    content: {
      type: String,
      required: true,
    },
  },
  setup(props) {
    const state = reactive({
      card: computed(() => props),
    })

    return { state }
  },
})
</script>

storybook에서 구성 요소 확인



storybook에서 작성한 컴포넌트의 props의 재기록 등이 정상적으로 동작하는지를 확인합니다.
Controls addon 을 사용하여 props를 다시 작성할 수 있습니다.

components/Card.stories.ts
import Card from './Card.vue'

export default {
  title: 'Card',
  argTypes: {
    title: {
      name: 'title',
      defaultValue: 'Free',
      control: {
        type: 'text',
      },
    },
    icon: {
      name: 'icon',
      defaultValue: 'github',
      control: {
        type: 'select',
        options: [
          'github',
          'cellphone-link',
          'alert-decagram',
          'arrange-bring-to-front',
        ],
      },
    },
    content: {
      name: 'content',
      defaultValue: '<a href="https://github.com/relishable">github</a>',
      control: {
        type: 'text',
      },
    },
  },
}

export const Normal = (args: any, { argTypes }: { argTypes: any }) => ({
  components: { Card },
  template:
    '<card :title="title" :icon="icon" :content="content"></card>',
  props: Object.keys(argTypes),
})


storybook을 실행하여 동작 확인


$ npx nuxt storybook



pages 이하로 비동기 데이터를 취득해, 화면 표시해 본다



이번 메인이 되는 곳.
지금까지, asyncData 메소드로 하고 있던 비동기 데이터 취득을 composition-api 로 해 보았습니다.

pages에 다음의 card.vue라고 하는 것을 만들고, 비동기 데이터용으로 static/json/data.json을 읽어들입니다.
nuxtjs/composition-api 가 준비해 준다
  • useContext
  • useAsync
  • useMeta

  • 를 사용해 보았습니다.

    pages/card.vue
    <template>
      <section class="section">
        <div class="columns">
          <template v-if="state.isLoading">読込中....</template>
          <template v-else>
            <card
              :title="card.title"
              :icon="card.icon"
              :content="card.content"
              :key="card.title"
              v-for="card in state.cards"
            >
            </card>
          </template>
        </div>
      </section>
    </template>
    
    <script lang="ts">
    import {
      defineComponent,
      reactive,
      useAsync,
      useContext,
      useMeta,
    } from '@nuxtjs/composition-api'
    import Card from '../components/Card.vue'
    
    export default defineComponent({
      name: 'Cards',
      head: {},
      components: {
        Card,
      },
      props: {},
      setup() {
        const { app } = useContext()
        const state = reactive({
          cards: [],
          isLoading: true,
        })
    
        useAsync(async () => {
          state.cards = await app.$axios.get('/json/data.json').then((res: any) => {
            return res.data.cards
          })
          state.isLoading = false
        })
    
        useMeta({ title: 'カード一覧' })
    
        return { state }
      },
    })
    </script>
    
    

    시작하여 동작 확인


    $ npm run dev
    

    액세스하면 순식간에 로드 중....이 표시된 후 카드 목록이 표시되었습니다.

    좋은 웹페이지 즐겨찾기