🔖
Vue でテンプレートとロジックを切り分ける | Vue3
概要
Vue でウェブアプリケーションを作っているときに、<script>
(ロジック)の部分は違うんだけど、<template>
(テンプレート)の部分は一緒、ということがあった。そこで、テンプレートとロジックを切り分けて、テンプレートは一つのファイルで使いまわして、ロジックは個々のファイルで管理できるよう構造を考えた。コンポーネントを使えばいいようなものだが、そうすると、テンプレート部分が全てコンポーネントに行ってしまう。テンプレートでは、いくつかのコンポーネントをすでに使用しており、もしテンプレートをコンポーネントにしてしまうと、コンポーネントからコンポーネントを呼び出す形になってしまい、管理が複雑になってしまうと思った。だから、今回はその手段を使わなかった。
環境
- Vue CLI で作った環境
- Vue3(Options API)
- Vuex4
構造
不要な部分は省略。
root/
├ views/
│ ├ LayoutView.vue
│ └ ChildrenView.vue
├ store/
├ └ index.js
└ App.vue ← 今回は関係ない
コード
Views 系
以下は、テンプレートを保持する Vue ファイル。一つだけ作成する。
LayoutView.vue
<template>
<div>
<!-- ここで共通のレイアウト(テンプレート)を設定する -->
<p>{{ $store.getters.getMessage }}</p>
<!-- 以下は必須(無いと、子のスクリプトが機能しない) -->
<router-view />
</div>
</template>
<style>
/* ここで様々なスタイルを設定する */
p {
font-weight: bold;
}
</style>
以下は、ロジックを保持する Vue ファイル。これを複数個作ることで、共通のテンプレートを持つアプリケーションを作成できる。
ChildrenView.vue
// 以下は必須(無いと、Vueから警告が出る)
<template></template>
<script>
// ここで様々なロジックを設定する
export default {
name: 'ChildrenView',
mounted() {
this.$store.commit('setMessage', 'Hello from ChildrenView');
},
};
</script>
Store 系
以下は Vuex のルートファイル。LayoutView と ChildrenView 間の変数のやり取りは Vuex を介して行う。
index.js
import { createStore } from 'vuex';
const store = createStore({
state() {
return {
message: 'No Message',
};
},
getters: {
getMessage: (state) => state.message,
},
mutations: {
setMessage: (state, msg) => {
state.message = msg;
},
},
});
Discussion