Nuxt 2 + Vuetify 2 + Vuex + jest -> Nuxt 3 + Vuetify 3 + Pinia + vitest / storybook利用への移行作業メモ
このスクラップは、来る2023年12月末にVue2 の EOLを迎えるための移行メモとしてのスクラップです。
Aliasの問題
Nuxt3が問題なのかIDEが問題なのか。原因不明。
vueファイルを読み込もうとするとエラーが発生する
Vue: Cannot find module @/components/AAA or its corresponding type declarations.
.vue
を指定して importすることで解決。
Nuxtの場合、Auto Importが有効であれば指定も不要。
追記メモとして、他のライブラリ vitest とかは unplugin-auto-import/vite
を使ってマッピングする。
Vue2で親から子のイベントを実行するときは 子コンポーネントのイベントに this.$ref.hogehoge.eventFunc
という形でthisでテンプレートにセットした refを実行していた。
Vue3 からは、 defineExpose({})
を子コンポーネントで関数をセットして、親側で子コンポーネントにセットした ref から参照して実行できる。
Vue2 子のコンポーネント
<template>
<button type="button" @click="event" />
</template>
<script>
export defalut {
method: {
event() {
console.log('event')
}
}
}
</script>
Vue2 親のコンポーネント
<template>
<Child ref="refChild" />
</template>
<script>
import Child from './Child'
export defalut {
components: { Child }
method: {
prarentEvent() {
this.$ref.refChild.event()
}
}
}
</script>
Vue3 子のコンポーネント
<template>
<button type="button" @click="event" />
</template>
<script setup lang="ts">
const event = () => console.log('event')
defineExpose({ // defineExpose
event
})
</script>
Vue3 親のコンポーネント
<template>
<Child ref="refChild" />
</template>
<script setup lang="ts">
import Child from './Child.vue'
const refChild = ref() // refを定義する
const prarentEvent = () => refChild.value.event() // refChild.valueから子のevent()を呼び出す
</script>
Storybookで、NuxtLinkはMock化する必要がある
Storybookを利用している場合、遭遇率が多いのは NuxtLinkといった Nuxtが固有で持ってる機能の取り扱いです。
Storybookでは識別できないので、preview.tsにNuxtLinkをMock化する必要があります。
具体的には以下のような形で aタグに変換させます。
import type { Preview } from '@storybook/vue3'
import { setup } from '@storybook/vue3'
import { action } from '@storybook/addon-actions' // addon-actionsはMethodの呼び出しとして利用する
setup((app) => {
if (app) {
app.component('NuxtLink', {
props: {
to: {
type: String,
required: true,
},
},
template: '<a :href="log"><slot></slot></a>',
setup(props, ctx) {
const log = action('link target', props.to)
return { log }
},
})
}
})
Vuetify 3 の VDataTable 変更点
headerの定義変更
-
text
->title
に変更 -
value
->key
に変更
hide-default-header / hide-defalut-footer廃止?
ヘッダーとフッターを非表示にする機能が VDataTableにはない。
ドキュメント差分
公式に方法書いてないのですが、以下で対応できる。
template #bottomで空で渡すことで非表示になるようです。(検証済み)
<template #bottom></template>
Nuxt 3 + Vuetify 3 + Storybookの構成でStorybookを立てた。
CloudFlare Pagesにデプロイしておいた。確認検証用
Vue3 から $listeners は削除され $attersに統合された。
独自に利用した 関数に Options API の thisを利用してた場合のComposition APIの書き方
Options API の this をそのまま 関数に使ってるコードをVue3のComposition APIに書き直すやり方。
Otions API では this を渡すと data や computedといった情報を取り出すことができる。
では、Composition APIの場合は thisがないため変更する必要があります。
具体的なイメージは以下のようなOptions API のコードをComposition APIに書き直した。
以下のコードはmessageという関数に thisを渡し関数の中で必要なプロパティを取り出して利用している。
Otions API
<script lang="ts">
import { defineComponent } from "vue";
import messages from "./messages";
// Options API
export default defineComponent({
data() {
return {
age: 18,
name: "vite",
};
},
computed: {
getMessage() {
return messages(this, "options API"); // <-- ここでthisを渡すとcomputedやdataの情報を代入できる
},
},
});
</script>
interface Option {
name: string;
age: number;
}
const messages = (option: Option, type: string) => {
console.log(option, type);
const { name, age } = option;
return `Hello ${name}, your age is ${age}`;
};
export default messages;
Composition API
Composition APIの場合、dataとして定義してた ageやnameといった情報を ref
や reactive
といった形で定義する必要がある。
それぞれの変数になるため、いままでの関数の呼び出しでthisを利用できない。
呼び出す前に必要な変数をまとめる必要です。
<script setup lang="ts">
import { ref, computed } from "vue";
import messages from "./messages";
const age = ref(18);
const name = ref("vite");
const getMessage = computed(() => {
const options = { name: name.value, age: age.value }; // <-- thisだった部分を一時的な変数にまとめる
return messages(options, "composition API"); // <-- ここでthisの代わりにoptionsに変更する
});
</script>
<template>
<div>
<h4>Composition API</h4>
<p>{{ getMessage }}</p>
</div>
</template>
codesandbox
Storybookでイベントをロギングする
ロギングするためには、必ず on
を接頭辞としてつける必要がある。
例えばupdate:model-valueの場合は以下のようにargTypesを設定する必要がある。
onUpdate:modelValue
argTypes: {
'onUpdate:modelValue': { action: 'modelValue' },
},
Nuxt 3 で storybookを起動させると useRuntimeConfig でエラーが発生して autoimportされる関数が使えない。
対応方法は、以下のようの .storybook/preview-body.html
を作成する
publicで設定している。nuxtのapiBaseも同様に設定することでエラーは解消できる。
<script>
const useRuntimeConfig = () => {
return {
isDevelopment: true,
public : {
apiBase: 'http://localhost:XXXXX'
}
}
}
</script>
VDateTable の expandで開閉する機能で 行自体をクリックする場合、 v2では @click:row
にイベントをつけてた。
v3でも @click:row
でイベントを貼って idなりを取得できるが、 props-expand-on-click
という propsが定義できるようになった。
これによって、ただの行をクリックするためのイベントを貼らずに props-expand-on-click にboolean渡せば行リックが実装できるようになった。
id を設定することで、rowの位置を確認できる。