Vue.js基本メモ

### Vueオブジェクト

```javascript
  <body>
    <div id="app">{{ message }}</div>
    <input type="text" oninput="doAction(event);" />

    <script>
      // 初期データ
      var data1 = {
        message: "please type",
      };

      // Vueオブジェクト
      var app = new Vue({
        el: "#app", // タグの属性(必須)
        data: data1, // elで指定したタグに渡す値
      });

      // inputされたとき、data1のmessageプロパティをそのinputの値に置き換える
      function doAction(event) {
        data1.message = event.target.value;
      }
    </script>
  </body>
```

### レンダリング

```javascript
  <body>
    <div id="app">{{ message }}</div>
    // 注: doAction()の結果、この<div>は無くなり、<p>clicked!</p> に置き換わる。

    <button onclick="doAction();">click</button>

    <script>
      var data1 = {
        message: "hello",
      };

      var app = new Vue({
        el: "#app",
        data: data1,
        // render: アロー関数
        render: (element) => {
          return element("p", data1.message); // 置き換える要素(タグ)
        },
      });

      function doAction() {
        data1.message = "clicked!";
      }
    </script>
  </body>
```

### v-html

```javascript
  <body>
    <div id="app">
      <!-- 受け取った「HTMLテキスト」をHTMLに変換 -->
      <ol v-html="messages"></ol>
    </div>

    <!-- 追加したいテキストの入力欄 -->
    <input type="text" oninput="doInput(event);" />

    <!-- 追加ボタン -->
    <button onclick="doAction();">click</button>

    <script>
      var data = {
        messages: "<li>hello</li>", // 1つ目のliタグ(以降、liタグが追加される)
      };

      var app = new Vue({
        el: "#app",
        data: data,
      });

      // inputの値を受け取る
      function doInput(event) {
        data.message = event.target.value;
      }
      // 受け取ったmessageをmessagesに追加
      function doAction() {
        data.messages += "<li>" + data.message + "</li>";
      }
    </script>
  </body>
```

### v-bind
```javascript
  <body>
    <style>
      .red {
        color: red;
      }
      .blue {
        color: blue;
      }
    </style>

    <div id="app">
      <!-- classesプロパティの値(=classObjオブジェクトのプロパティの真偽値)
        によって、pタグのクラスが決まる
        trueのプロパティがクラス名になる -->
      <p v-bind:class="classes">{{ message }}</p>
    </div>
    <button onclick="doAction();">click</button>

    <script>
      // 初期状態は、文字が赤色
      var classObj = {
        red: true,
        blue: false,
      };

      var data = {
        message: "hello",
        classes: classObj,
      };

      var app = new Vue({
        el: "#app",
        data: data,
      });

      function doAction() {
        classObj.red = !classObj.red;
        classObj.blue = !classObj.blue;
      }
    </script>
  </body>
```

### v-if, v-else
指定したプロパティの真偽値によるif分岐を行う。

### v-for

```javascript
  <body>
    <div id="app">
      <!-- v-forで取り出したitemを、v-bindでcomponentにnameとして渡す -->
      <test v-for="item in data" v-bind:name="item" />
    </div>

    <script>
      Vue.component("test", {
        props: ["name"],
        template: `<p class="test">{{ name }}!</p>`,
      });

      var app = new Vue({
        el: "#app",
        data: {
          data: ["taro", "hanako", "jiro"],
        },
      });
    </script>
  </body>
```

### v-model

```javascript
  <body>
    <div id="app">
      <div>
        <!-- 3. 2.で更新されたnameを、コンポーネントのnameにも反映する -->
        <sample v-bind:name="name" />
      </div>
      <div>
        <!-- 1. Vueオブジェクトのdataプロパティのnameに紐付ける -->
        <input type="text" v-model="name" />
      </div>
    </div>

    <script>
      Vue.component("sample", {
        props: ["name"],
        // 4. 3.に記載のとおり
        template: `<p class="sample">{{ name }}</p>`,
      });

      var app = new Vue({
        el: "#app",
        data: {
          // 2. inputタグの内容が、nameが更新される
          name: "何か入力してください",
        },
      });
    </script>
  </body>
```

### v-on

```javascript
<body>
    <style>
      .red {
        color: red;
      }
    </style>

    <div id="app">
      <sample />
    </div>

    <script>
      Vue.component("sample", {
        data: function () {
          return {
            counter: 0,
            isRed: false,
          };
        },
        methods: {
          doAction: function (event) {
            this.counter++;
            // counterが奇数なら文字を赤色にする
            if (this.counter % 2 == 0) {
              this.isRed = false;
            } else {
              this.isRed = true;
            }
          },
        },
        /* v-onで、clickするとこのコンポーネントのdoActionを呼ぶ
           v-bindで、isRed値によってredクラスにするか決める */
        template: `<p v-on:click="doAction" v-bind:class="{red: isRed}">{{ counter }}</p>`,
      });

      var app = new Vue({
        el: "#app",
      });
    </script>
  </body>
```

### \<template>タグ
[Vue.jsの <template>タグには複数の役割がある](https://qiita.com/m_norii/items/c52171fd09c4504f8b81)
この記事がわかりやすく、まとまっている。

## コンポーネント

### 定義
Vue.component( 名前, {設定情報(オブジェクト)} );

### 利用
< コンポーネント名 />

### プロパティ
- templateプロパティ
ここに記載した内容が表示される

- dataプロパティ
変数をまとめたオブジェクトをreturnする**関数**を記載する。
(Vueオブジェクトは、オブジェクトを記載)

- propsプロパティ

```javascript
  <body>
    <div id="app">
      <!-- 1 -->
      <div><hello name="Taro" /></div>
      <div><hello name="Hanako" /></div>
    </div>

    <script>
      Vue.component("hello", {
        props: ["name"], // 2
        // <!-- helloタグのname属性値へ共有される(= 1~3は同じ値になる) -->
        template: `<p class="hello">{{ name }}!</p>`, // 3
      });

      var app = new Vue({
        el: "#app",
      });
    </script>
  </body>
```

- methodsプロパティ
イベントの処理関数を記載する。

- computedプロパティ

```javascript
  <body>
    <div id="app">
      <sample />
    </div>

    <script>
      Vue.component("sample", {
        data: function () {
          return {
            num: 0,
          };
        },
        computed: {
          /* 2. calcはnumに依存することを知っているので、
                numが変更されるとcalcも自動的に変更(計算)される */
          calc: function (event) {
            var total = 0;
            for (var i = 1; i <= this.num; i++) {
              total += i;
            }
            return total;
          },
        },
        // 1. inputタグで紐付いているnumが変更される
        template: `<div><p>{{ calc }}</p>
            <div><input type="number" v-model="num"></div>
            </div>`,
      });

      var app = new Vue({
        el: "#app",
      });
    </script>
  </body>
```