水無瀬のプログラミング日記

プログラムの勉強した時のメモ

Vue.jsを使ってみる

TL;DR.

ソースはここ

はじめに

主に使っているのはAngularだけど、フロントエンドやっているのに他の名前しか知らないですはどうなんだろうと思い勉強を決意。
目標は色んな所に乗ってるVueのコードが読めること。
後は、Angularとの違いとかもちゃんと自力で説明できると良いなくらい。
※ちなみに公式サイトに他FWとの比較は載ってる。

ついでに前々からやろうと思ってたSCSSも触れてみる。

Vue.jsとは

JavascriptのUIを構築するためのFW。
UIメインだけど、SPAも構築可能。
作成者はEvan You。
詳しくはVue.jsの公式サイトに書いてある。

インストール~セットアップ

# cliのインストール
$ npm install -g @vue/cli

# プロジェクトの作成
$ vue create 【プロジェクト名】

Vue CLI v3.0.5
? Please pick a preset:
  default (babel, eslint)
> Manually select features
# 色々効かれるのでお好みで
? Check the features needed for your project: TS, Router, CSS Pre-processors, Linter, Unit, E2E
.
.
.
# インストールが始まり、下記が表示されて終わる
⚓  Running completion hooks...

📄  Generating README.md...

🎉  Successfully created project ts-vue.
👉  Get started with the following commands:

 $ cd ts-vue
 $ npm run serve

アプリ作成

よくサンプルとして作られるToDoアプリを作ってみる。
ただし、やるのはUIだけ。テキストボックスに入れてボタンを押したらデータが入るところで満足する。 上で作成されたプロジェクトをベースにファイルは書き換えじゃなくて追加でやる。

Component作成

とりあえず書いたものから。
ファイルはcomponents配下にList.vueという名前で作成。

Vue.jsでは1つのファイルにHTML(templateタグ内)とjavascript(scriptタグ内。ts使う時はlang="ts"で書ける)、css(scssとか他のを使いたければ、これもlangを変える)を書くらしい。
Angularでも同じファイルに書けないことは無いだろうけど、あんまり見ないしこれは新鮮だった。
ちなみにtemplateタグ内にはDOMを1つしか書けないっぽい。なので、サンプルでは<div></div>で囲って1つだけにしてる。

作ったアプリでやっていることは、テキストボックスの内容をボタンを押したときにリストに追加するだけ。
作り方としては、テキストボックスの中身はscriptと双方向でバインド。 ボタンを押した時にテキストの内容をリストへ追加している。
リストはループで全件表示。
Angularみたく、addTodo(data.target.value)みたいな書き方をしたかったけど、やり方が分からなかったからこのやり方。

List.vue(components/List.vue)

<template>
<div>
    // v-model="todo"と書くことで変数todoと双方向でバインドできる。
    // angularで言うとこの[(ngModel)]="todo"
    <input type="text" id="data" v-model="todo">
    // @clickでclickイベントをハンドリングできる。
    // angularで言うとこの(click)="addTodo"と同じ。
    <button @click="addTodo()">登録</button>
    <ul id="list">
        // v-forは普通のループ。
        // angul(ry *ngForと同じ。
        <li v-for="todoItem in todoList">
            {{todoItem}}
        </li>
    </ul>
</div>
</template>
<script lang="ts">
import Vue from 'vue';
import Component from 'vue-class-component';
import { Prop } from 'vue-property-decorator';

// @Component デコレータはクラスが Vue コンポーネントであることを示します
@Component({})
export default class ListComponent extends Vue {
  // Componentの呼び出し元から値を受け取りたいときはProp()でできる。  
  @Prop() public addItems!: string[];
  private todo: string = '';
  private todoList: string[] = [];

  constructor() {
      super();
      this.todoList = this.todoList.concat(this.addItems);
  }

  private addTodo() {
      this.todoList.push(this.todo);
      this.todo = '';
  }
}
</script>
<style lang="scss" scoped>
ul {
    margin-left: auto;
    margin-right: auto;
    width: 300px;
    li:nth-child(even) {
        color: blue;
    }
}
#list {
    text-align: left
}
</style>

Todo.vue(views/Todo.vue)

<template>
  <div class="todo">
    // LitComponentを呼び出し、addListを渡してる。  
    <ListComponent :addItems="addList"/>
  </div>
</template>
<script lang="ts">
import { Component, Vue } from 'vue-property-decorator';
import ListComponent from "@/components/List.vue";

@Component({
  components: {
    ListComponent,
  },
})
export default class Todo extends Vue {
    public addList = ['test1', 'test2'];
}
</script>

実行する

package.jsonにscriptが追加されているのでそれを使う。
npm run serveで起動する。挙動はng serveと同じ感じ。
ちなみ他にはnpm run buildnpm run lintが追加されてた。
以下画像が実行イメージ。意味もなく偶数列の色を変えてみた。

f:id:minase_mira:20181103001354p:plain f:id:minase_mira:20181103001402p:plain

まとめ

思ってた以上にとっつきやすかった。
ちょっと勉強すれば簡単なSPAなら作れそうな感じ。
1つのファイル(.vueファイル)にHTML、JavascriptCSSがまとまってるからわかりやすい気がする。
人気が出るのもなるほどなーって思った。