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> ```