https://cli.vuejs.org/guide/
[[Vue CLI]]を使って構築し、以下の要素を導入する。
- [[TypeScript]]
- [[Composition API]]
- [[Vuetify]]
設定はミニマムにする。
## Vue CLIのインストール
インストールされていなければ[[Vue CLIのインストール]]に従う。
バージョン確認
```shell
$ vue --version
@vue/cli 4.5.11
```
## TypeScriptプロジェクトを作成する
[[Vue CLIでTypeScriptプロジェクトを作成]]の方法をベースに実行。
```shell
vue create vue2-typescript-vuetify
```
設定は下記。
```shell
? Please pick a preset: Manually select features
? Check the features needed for your project: Choose Vue version, TS, Linter
? Choose a version of Vue.js that you want to start the project with 2.x
? Use class-style component syntax? No
? Use Babel alongside TypeScript (required for modern mode, auto-detected polyfills, transpiling JSX)? No
? Pick a linter / formatter config: Prettier
? Pick additional lint features:
? Where do you prefer placing config for Babel, ESLint, etc.? In dedicated config files
? Save this as a preset for future projects? (y/N)
```
### 動作確認
```shell
cd vue2-typescript-vuetify
npm run serve
```
`localhost:8080`にアクセスして画面が表示されればOK。
### 構成
```ls
.
├── package-lock.json
├── package.json
├── public
│ ├── favicon.ico
│ └── index.html ブラウザからのエントリポイント
├── README.md
├── src
│ ├── ﵂ App.vue Viewのエントリポイント
│ ├── assets 画像などの静的ファイル
│ │ └── logo.png
│ ├── components コンポーネントはこの下に
│ │ └── ﵂ HelloWorld.vue
│ ├── main.ts エントリポイント
│ ├── shims-tsx.d.ts tsxファイルを読み込むおまじない
│ └── shims-vue.d.ts vueファイルを読み込むおまじない
├── tsconfig.json
└── vue.config.js ???
```
## Vuetifyの導入
[[Vuetify]]を導入して見た目を格好よくする。
https://vuetifyjs.com/ja/getting-started/installation/
```shell
$ vue add vuetify
...
? Choose a preset: Default (recommended)
...
```
もう一度`npm run serve`してオシャレな画面が出ればOK。
## Composition APIの導入
[[Composition API]]を取り込む。今回は[[Vue2]]なので[[composition-api plugin]]を使う。
```shell
npm install @vue/composition-api
```
`main.ts`で適応する。
```diff
import Vue from "vue";
import App from "./App.vue";
import vuetify from "./plugins/vuetify";
+ import VueCompositionAPI from "@vue/composition-api";
Vue.config.productionTip = false;
+ Vue.use(VueCompositionAPI);
new Vue({
vuetify,
render: h => h(App)
}).$mount("#app");
```
`HelloWorld.vue`をまた書き換える。よく使うパターンを一通り盛り込んだものにする。
```vue
<template>
<v-container>
<v-row class="justify-center text-center">
<v-col cols="12">
<h1>{{ msg }}</h1>
</v-col>
<v-col cols="2">
<v-text-field
v-model="state.inputValue"
label="好きな数字は?"
></v-text-field>
</v-col>
<v-col cols="12" v-if="canDouble">
<p>
<span>{{ state.inputValue }}の2倍した値は</span>
<b v-text="doubleNumber"></b>
<span>ですな</span>
</p>
</v-col>
<v-col cols="12">
<div class="ma-5">
<v-btn @click="handleClick" :disabled="!canDouble">
アラートを出す
</v-btn>
</div>
</v-col>
</v-row>
</v-container>
</template>
<script lang="ts">
import {
defineComponent,
reactive,
computed,
watch,
onMounted
} from "@vue/composition-api";
export default defineComponent({
// 別のVueコンポーネントを使う場合はここに追加していく
components: {
// SampleComponent,
},
// <hello-world msg="おはござ" /> のように指定できる属性
// 以前の書き方だとpropsに相当する
props: {
msg: { type: String, default: "おはござ" }
// Array型の場合は↓のように書く。各要素はHuga型の場合
// huga: { type: Array as () => Huga[] },
// primitive型でもArrayでもない場合は↓のように書く
// required: true を指定すると必須になる
// hoge: { type: Object as () => Hoge, required: true },
},
setup() {
// - Componentの状態はstateとして管理する
// - reactiveによって変更があった場合に必要な処理を実行できる
// - 以前の書き方だとdataに相当する
const state = reactive({
inputValue: "0" as string | undefined
});
// - 算出プロパティはcomputedでfunctionをラップする
// - 別の変数に変更があった場合自動で再計算される
// - 以前の書き方だとcomputedに相当する
const canDouble = computed(
() =>
state.inputValue !== undefined && /^-?[0-9]+$/.exec(state.inputValue)
);
const doubleNumber = computed(() =>
canDouble ? Number(state.inputValue) * 2 : undefined
);
const message = computed(() => `入力した値は${state.inputValue}です`);
// 関数は普通に定義する
const handleClick = () => {
window.alert(message.value);
};
// - 特定の値に変更があったときに処理を行う場合はwatchを使う
// - 算出プロパティで実現できる場合はcomputedを使う
// - 以前の書き方だとwatchに相当する
watch(
// 監視対象のプロパティ
() => state.inputValue,
// 変更があったときのアクション。ここではコンソールに出力している
val => console.log(`新しい値は ${val}`)
);
// ライフサイクルイベントはonXXXでfunctionをラップする
// たとえば、mountedの場合はonMountedになる
onMounted(() => {
window.alert("mount完了!!");
});
// Viewから参照するためにreturnで返却する
return {
state,
canDouble,
doubleNumber,
handleClick
};
}
});
</script>
<style scoped>
h1 {
color: green;
}
</style>
```