Vue入門14 propsをcomputed処理して利用する

Vue入門の第14回(第1回はこちら)です。今回は、受け取ったpropsをコンポーネント内でcomputed処理して利用する方法を学びます。

index.htmlを書き換える

前回作成したHTMLファイル index.html を以下のように書き換えます。

<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <title>Vueサンプル</title>
    <script src="https://unpkg.com/vue"></script>
</head>
<body>
<div id="app">
    <item catchcopy="再入荷しました!" pointup="true"></item>
    <item></item>
    <item></item>
</div>
<script src="main.js"></script>
</body>
</html>

前回の書き換えでは、3つある<item></item>のひとつに「catchcopy=”再入荷しました!”」というカスタム属性を追加しました。今回の書き換えでも同じように「pointup=”true”」というカスタム属性を追加します。

このカスタム属性 pointup の値を、itemコンポーネントにpropsとして受け渡します。

main.jsを書き換える

前回作成したJSファイルmain.jsを以下のように書き換えます。

Vue.component('item', {
    props: {
        catchcopy: {
            type: String,
            default: '定番商品'
        },
        pointup: {
            type: Boolean,
            default: false,
            required: true
        }
    },
    template: `
        <div class="item">
            <div class="item-image">
                <img v-bind:src="itemImage" />
            </div>
    
            <div class="item-info">
                <h2>{{ itemFullName }}</h2>
                <ul><li v-for="itemInfo in itemInfos">{{ itemInfo }}</li></ul>
                <p>※{{ catchcopy }}</p>
                <p>※ポイント付与率:{{ pointRate }}%</p>
                <p v-if="zaiko > 2">在庫あり</p>
                <p v-else-if="zaiko <= 2 && zaiko > 0">残りわずか!</p>
                <p v-else>在庫なし</p>

                <div 
                v-for="itemColor in itemColors" 
                v-on:click="changeColor(itemColor.cImage, itemColor.cName)" 
                v-bind:style="{ backgroundColor: itemColor.cCode }" 
                style="width:30px; height:30px; margin-bottom:20px;"
                >
                </div>
    
                <button 
                v-on:click="addCart" 
                v-bind:disabled="soldout"
                >買い物かごの中身を増やす</button>
                <div class="cart">
                    <p>買い物かごの中身 {{ cart }}</p>
                </div>
            </div>
        </div>
    `,
    data() {
        return {
            itemName: 'キッズ靴下',
            itemColorName: 'ピンク',
            itemImage: './images/socks-pink.png',
            itemInfos: ["子供向け靴下", "コットン100%", "人気商品!"],
            itemColors: [
                {cName:"ピンク", cCode:"#ee6699", cImage:"./images/socks-pink.png"},
                {cName:"ブルー", cCode:"#33aaee", cImage:"./images/socks-blue.png"}
            ],
            zaiko: 5,
            cart: 0,
            soldout: false
        }
    },
    methods: {
        addCart: function () {
            this.cart += 1
            this.zaiko -= 1
            if (this.zaiko <= 0) {this.soldout = true}
        },
        changeColor (cImage, cName) {
            this.itemImage = cImage,
            this.itemColorName = cName
        }
    },
    computed: {
        itemFullName() {
            return this.itemName + '(' + this.itemColorName + ')'
        },
        pointRate() {
            if (this.pointup) {
                return 2
            } else {
                return 1
            }
        }
    }
})

var app = new Vue({
    el: '#app'
})

今回のmain.jsの書き換えでは、以下の3点が変更されています。

  1. propsプロパティのなかにpointupというpropの指定が追加されています。
  2. computedプロパティのなかに、pointRate()が追加されています。
  3. templateプロパティのなかに <p>※ポイント付与率:{{ pointRate }}%</p> の一行が追加されています。

表示を確認してみる

ここまで出来たら、index.htmlとmain.jsを上書き保存して表示を確認してみましょう。以下は、今回作成したサンプルページです。

https://programming-world.net/sample/vue_sample/14/index.html

<item catchcopy=”再入荷しました!” pointup=”true”></item> と指定したitemコンポーネントで、「※ポイント付与率:2%」が表示されれば成功です。

<item></item> とだけ指定した2つのitemコンポーネントでは、 「※ポイント付与率:1%」と表示されているはずです。

今回の変更点を詳しく確認

あらためて今回の変更点を詳しく確認していきましょう。今回のmain.jsの書き換えでは、以下の3点が変更されています。

  1. propsプロパティのなかにpointupというpropの指定が追加されています。
  2. computedプロパティのなかに、pointRate()が追加されています。
  3. templateプロパティのなかに <p>※ポイント付与率:{{ pointRate }}%</p> の一行が追加されています。

1. propsプロパティのなかに pointup を追加

1点目の変更では、propsプロパティのなかにpointupという名前を付けたpropの指定が追加されています。

    props: {
        catchcopy: {
            type: String,
            default: '定番商品'
        },
        pointup: {
            type: Boolean,
            default: false,
            required: true
        }
    },

上記コードでは、pointupという名前を付けたpropは、タイプはBoolean型、初期値は false 、必須かどうかは true と指定しています。

2. computedプロパティのなかに pointRate() を追加

2点目の変更では、computedプロパティのなかに pointRate() が追加されています。

    computed: {
        itemFullName() {
            return this.itemName + '(' + this.itemColorName + ')'
        },
        pointRate() {
            if (this.pointup) {
                return 2
            } else {
                return 1
            }
        }
    }

上記コードでは、コンポーネントに渡された pointup という名前の prop を「this.pointup」で受け取って利用しています。 this.pointup の値がtrueなら2を返し、falseなら1を返しています。

templateプロパティのなかにポイント付与率を表示するp要素を追加

3点目の変更では、templateプロパティのなかに <p>※ポイント付与率:{{ pointRate }}%</p> の一行が追加されています。

template: `
    (中略)
    <p>※ポイント付与率:{{ pointRate }}%</p>
    (中略)
`,

上記コードでは、ここでは、computedプロパティのなかのpointRate()で計算した結果をp要素として画面に表示しています。

まとめ

今回は、受け取ったpropsをコンポーネント内でcomputed処理して利用しました。

  • props のタイプには、前回登場したString型以外に、今回登場したBoolean型があります。 Boolean型は true / false を値に持ちます。
  • 受け取ったpropsは「this.pointup」という具合にthis.props名で指定できます。「このコンポーネント内のpointupの値」という意味です。

次回へ続きます。