jtk

【学習メモ】Vue.js入門 基礎から実践アプリケーション開発まで その2

3 コンポーネントの基礎

3.2 Vue コンポーネントの定義

3.2.1 グローバルコンポーネントの定義

<!-- グローバルコンポーネント -->
<div id="app">
  <fruits-list-title></fruits-list-title>
  <fruits-list-description></fruits-list-description>
  <fruits-list-table></fruits-list-table>
  <fruits-list></fruits-list>
</div>
// グローバルコンポーネント
Vue.component("fruits-list-title", {
  template: `<h1>一覧</h1>`
});

Vue.component("fruits-list-description", {
  template: `<p>ここに説明が入ります</p>`
});

Vue.component("fruits-list-table", {
  template: `
  <table>
    <tr>
      <th>季節</th>
      <th>フルーツ</th>
    </tr>
    <tr>
      <td>春</td>
      <td>いちご</td>
    </tr>
    <tr>
      <td>夏</td>
      <td>スイカ</td>
    </tr>
  </table>
`
});

// 子コンポーネント
Vue.component("fruits-list", {
  template: `<div><fruits-list-table></fruits-list-table></div>`
});

// Vue のマウント
var app = new Vue({
  el: "#app"
});

3.2.3 ローカルコンポーネントの定義

<!-- ローカルコンポーネント -->
<div id="app">
  <fruits-list-title></fruits-list-title>
  <fruits-list-description></fruits-list-description>
  <fruits-list-table></fruits-list-table>
  <fruits-list></fruits-list>
</div>
// ローカルコンポーネント
// Vue のマウント
var app = new Vue({
  el: "#app",
  components: {
    "fruits-list-title": {
      template: `<h1>一覧</h1>`
    },
    "fruits-list-description": {
      template: `<p>ここに説明が入ります</p>`
    },
    "fruits-list-table": {
      template: `
      <table>
        <tr>
          <th>季節</th>
          <th>フルーツ</th>
        </tr>
        <tr>
          <td>春</td>
          <td>いちご</td>
        </tr>
        <tr>
          <td>夏</td>
          <td>スイカ</td>
        </tr>
      </table>`
    }
  }
});

3.3 コンポーネント間の通信

コンポーネント → 子コンポーネント への通信: props
コンポーネント → 親コンポーネント への通信: event

3.3.1 親コンポーネントから子コンポーネントへデータ伝播

props の例

<!-- 親が `fruits-component` にマウントされたインスタンス -->
<div id="app">
  <ol>
    <!-- `v-for` で繰り返した各fruitを `props(fruits-item)に与えている` -->
    <fruits-item-name
      v-for="fruit in fruitsItems"
      :key="fruit.name"
      :fruits-item="fruit"
    ></fruits-item-name>
  </ol>
</div>
Vue.component("fruits-item-name", {
  props: {
    fruitsItem: {
      // テンプレート中ではケバブケース
      type: Object, // オブジェクトかどうか
      required: true // このコンポーネントには必須なので `true`
    }
  },
  template: "<li>{{fruitsItem.name}}</li>"
});

// Vue のマウント
var app = new Vue({
  el: "#app",
  data: {
    // 親では配列だが、`v-for` で `Object` として渡している
    fruitsItems: [{ name: "梨" }, { name: "いちご" }]
  }
});

3.3.2 子コンポーネントから親コンポーネントへデータ伝播

カスタムイベントを使用

<!-- カスタムイベントを `v-on` で補足 -->
<div id="app">
  <div v-for="fruit in fruits">
    {{ fruit.name }}:
    <counter-button v-on:increment="incrementCartStatus()"></counter-button>
  </div>
  <p>合計: {{ total }}</p>
</div>
var counterButton = Vue.extend({
  template: `<span>{{counter}}個<button v-on:click="addToCart">追加</button></span>`,
  data: function() {
    return {
      counter: 0
    };
  },
  methods: {
    addToCart: function() {
      this.counter += 1;
      this.$emit("increment"); // `increment`カスタムイベントの発火
    }
  }
});

// Vue のマウント
var app = new Vue({
  el: "#app",
  components: {
    "counter-button": counterButton
  },
  data: {
    total: 0,
    fruits: [{ name: "梨" }, { name: "いちご" }]
  },
  methods: {
    incrementCartStatus: function() {
      this.total += 1;
    }
  }
});

3.4 コンポーネント間の設計

3.3.4 ログインフォームコンポーネントの作成

<div id="login-example"><user-login></user-login></div>
// コンポーネントの定義
Vue.component("user-login", {
  template: `
  <div id="login-template">
    <div>
      <input type="text" placeholder="ログインID" v-model="userid">
    </div>
    <div>
      <input type="password" placeholder="パスワード" v-model="password">
    </div>
    <button @click="login()">ログイン</button>
  </div>
  `,
  data: function() {
    return {
      userid: "",
      password: ""
    };
  },
  methods: {
    login: function() {
      auth.login(this.userid, this.password);
    }
  }
});

var auth = {
  login: function(id, pass) {
    window.alert("userid:" + id + "\n" + "password:" + pass);
  }
};

// Vue のマウント
var app = new Vue({
  el: "#login-example"
});