Vue2ではdataやcomputed、mountedなどoptionsごとにロジックをまとめて記述するOptions APIだったが、Vue3でリリースされたComposition APIではロジックを中心に自由に関数定義できる。Composition APIがこれからの主流になりそうなので切り替えていきましょう。Laravelから利用する方法とVue3でのコンポーネントの作成方法などをまとめておきます。
目次
開発環境
Windows10
Docker Desktop
WSL2
Laravel9
Laravel Sail
Vue3のインストール&設定
Vue3のインストール
$ sail npm install vue@next vue-loader@next @vitejs/plugin-vue
Viteの設定
import { defineConfig } from 'vite';
import laravel from 'laravel-vite-plugin';
import vue from '@vitejs/plugin-vue' // 追加
export default defineConfig({
plugins: [
laravel([
'resources/css/app.css',
'resources/js/app.js',
]),
vue(), // 追加
],
server: {
hmr: {
host: 'localhost',
},
},
});
Laravelの設定
Route::get('/app/{any?}', function() {
return view('app');
});
<!doctype html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- CSRF Token -->
<meta name="csrf-token" content="{{ csrf_token() }}">
<title>{{ config('app.name', 'Laravel') }}</title>
<!-- Fonts -->
<link rel="dns-prefetch" href="//fonts.gstatic.com">
<link href="https://fonts.bunny.net/css?family=Nunito" rel="stylesheet">
<!-- Scripts -->
@vite(['resources/css/app.css', 'resources/js/app.js'])
</head>
<body>
<div id="app"></div>
</body>
</html>
インスタンスの生成
import './bootstrap';
import { createApp } from 'vue'
import App from './components/App.vue'
const app = createApp(App)
app.mount("#app")
基本レイアウトはApp.vueで行って、VueRouterで画面切り替えればいいね。
コンポーネント呼び出し
app.jsでコンポーネントをインポート
import './bootstrap';
import { createApp } from 'vue'
import App from './components/App.vue'
import TestHeader from './components/UserHeader.vue'
import TestFooter from './components/UserFooter.vue'
const app = createApp(App)
app.component('user-header', UserHeader)
app.component('user-footer', UserFooter)
app.mount("#app")
<template>
<user-header />
<router-view />
<user-footer />
</template>
app.vueでコンポーネントをインポート
<template>
<user-header />
<router-view />
<user-footer />
</template>
<script>
import UserHeader from './components/UserHeader.vue'
import UserFooter from './components/UserFooter.vue'
<script>
この場合はパスカルケースとケバブケースのどちらでも呼び出すことができるのね。
<UserHeader />
<user-header />
また、is属性で呼び出すこともでき、動的にコンポーネントを切り替えることもできるみたいね。
<component :is="UserHeader"/>
Vueコンポーネント作成
従来の「Options API」でも、Vue3から導入された「Composition API」でも、さらにVue3.2から導入された「構文」でも作成することができる。書き方の違いを確認しておきましょう。
ライフサイクルフックについは名称が変わってるので要確認ね。
https://v3.ja.vuejs.org/guide/composition-api-lifecycle-hooks.html
Options APIで作成
<template>
<h1>Counter</h1>
<p>Count: {{ count }}</p>
<p>doubleCount: {{ doubleCount }}</p>
<button @click="increment">++</button>
</template>
<script>
export default {
data() {
return {
count: 0,
}
},
computed: {
doubleCount: function() {
return this.count * 2
},
},
mounted() {
console.log("mounted.")
},
watch: {
doubleCount(val, old) {
console.log(old)
}
},
methods: {
increment: function() {
this.count++
},
},
}
</script>
Composition APIで作成
<template>
<h1>Counter</h1>
<p>Count: {{ count }}</p>
<p>doubleCount: {{ doubleCount }}</p>
<button @click="increment">++</button>
</template>
<script>
import { defineComponent, ref, computed, onMounted, watch } from 'vue'
export default defineComponent({
setup() {
const count = ref(0)
const doubleCount = computed(() => {
return count.value * 2
})
onMounted(() => {
console.log("mounted.")
})
watch(doubleCount, (val, old) => {
console.log(old)
})
const increment = () => {
count.value++
}
return {
count,
doubleCount,
increment,
}
}
})
</script>
使用する関数はimportしないといけないのね。
ref関数については後ほど…
<script setup>構文で作成
<template>
<h1>Counter</h1>
<p>Count: {{ count }}</p>
<p>doubleCount: {{ doubleCount }}</p>
<button @click="increment">++</button>
</template>
<script setup>
import { ref, computed, onMounted, watch } from 'vue'
const count = ref(0)
const doubleCount = computed(() => {
return count.value * 2
})
onMounted(() => {
console.log("mounted.")
})
watch(doubleCount, (val, old) => {
console.log(old)
})
const increment = () => {
count.value++
}
</script>
・export default defineComponent({ setup() {} })を省略できる!
・returnもしなくていい!
と簡単!
書き方がいろいろあると困るんだけど、簡単なほうがいいのでこれからは<script setup>構文で!
refとreactiveについて
Composition APIではリアクティブな変数は明示的に定義しなければならないのね。
<template>
<h1>Ref/Reactive</h1>
<p>Count: {{ count }}</p>
<p>UserCount: {{ user.count }}</p>
<button @click="increment">++</button>
</template>
<script setup>
import { ref, reactive } from 'vue'
const count = ref(0)
const user = reactive({
name: 'taro',
count: 0,
})
const increment = () => {
count.value++
user.count++
}
</script>
ref関数
・プリミティブ(オブジェクト以外)を対象にリアクティブな変数として定義。
・唯一のプロパティ「value」を持ち、値の取得・操作にはこのvalueプロパティを操作。
・<template>内ではアンラップされvalueが表示される。
reactive関数
・オフジェクトを引数にリアクティブにしたコピーを返す。
・reactiveで定義した値については各プロパティを直接操作できる。
その他
<template>が先かが先か問題
Vue3から公式の順番が<template>→<script>になっているが、プロジェクト全体で統一されていれば逆でも良いらしい。
[参考]単一ファイルコンポーネントのトップレベルの属性の順序