前回の記事から続いて、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オプションに追記
{
buildModules: [
'@nuxtjs/composition-api'
]
}
jest用の設定を追加
※ この記事では、jestについては書かないのですが、今後書くので一応。
moduleNameMapper: {
'@nuxtjs/composition-api': '@nuxtjs/composition-api/lib/cjs/entrypoint.js',
},
composition-apiの形式に既存のコンポーネントを書き換え
Nuxt.js + buefyでインストールした場合に
デフォルトで作成されている、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の書き換えができるようにしました。
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
を使ってやってみました。
<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
アクセスすると一瞬、読み込み中....が表示されたあとカード一覧が表示されました。