公式ホームページのIntro to Vue 3クラス8 (Computed Properties)

# 8. Computed Properties

>クラス https://www.vuemastery.com/courses/intro-to-vue-3/computed-properties-vue3

VS Codeから該当フォルダを選択して、開きます。その後に、配下のgit部分をクリックして、ブランチをL8-startへ入れ替えてください。

>ブランチ切り替え方法 https://qiita.com/phjg81/items/e6695eb2334d9297a318

今日のポイントはcomputed属性を利用して、variantイメージと在庫要否を一緒に制御することです。

brandとproductを結合して、表示する一番簡単な方法は以下になります。

```html:index.html
<h1>{{ brand + ' ' + product }}</h1>
```

ユーザにより、変化される値だったりする場合はVueのデータオブジェクトから結合する方法がより良いと思います。

```html:index.html
<h1>{{ title }}</h1>
```

```javascript:main.js
const app = Vue.createApp({
    data() {
        return {
            ...
        }
    },
    methods: {
        ...
    },
    computed: {
      title() {
        return this.brand + ' ' + this.product
      }
    }
})

```

では、computed属性を利用して、variantイメージと在庫要否を一緒に制御することをやります。
variantsへquantityを追記します。

```javascript:main.js：quantityを追記
const app = Vue.createApp({
    data() {
        return {
            ...
            variants: [
              { id: 2234, color: 'green', image: './assets/images/socks_green.jpg', quantity: 3 },
              { id: 2235, color: 'blue', image: './assets/images/socks_blue.jpg', quantity: 0 },
            ]
    },
    methods: {
        ...
    },
    computed: {
      title() {
        return this.brand + ' ' + this.product
      }
    }
})

```

```html:index.html
            <div 
              class="color-circle" 
              v-for="variant in variants" 
              :key="variant.id" 
              @mouseover="updateImage(variant.image)" 
              :style="{ backgroundColor: variant.color }"></div>
```

```html:index.html：パラメータindexを追記
            <div 
              class="color-circle" 
              v-for="(variant, index) in variants" 
              :key="variant.id" 
              @mouseover="updateVariant(index)" 
              :style="{ backgroundColor: variant.color }"></div>
```

```javascript:main.js：selectedVariantを追記
const app = Vue.createApp({
    data() {
        return {
            ...
            selectedVariant: 0
    },
    methods: {
        ...
    },
    computed: {
      ...
    }
})

```

```javascript:main.js：updateImageをupdateVariantへ変更
const app = Vue.createApp({
    data() {
        return {
            ...
    },
    methods: {
        addToCart() {
            this.cart += 1
        },
        updateVariant(index) {
            // this.image = variantImage
            this.selectedVariant = index
        }
    },
    computed: {
      ...
    }
})

```

```javascript:main.js：computed属性として、imageとinStock追記と既存imageとinStockは削除
const app = Vue.createApp({
    data() {
        return {
            ...
            // image: './assets/images/socks_blue.jpg',
            // inStock: false,
            ...
        }
    },
    methods: {
        addToCart() {
            this.cart += 1
        },
        updateVariant(index) {
            // this.image = variantImage
            this.selectedVariant = index
        }
    },
    computed: {
      title() {
        return this.brand + ' ' + this.product
      },
      image() {
        return this.variants[this.selectedVariant].image
      },
      inStock() {
        return this.variants[this.selectedVariant].quantity
      }
    }
})

```
結果はこのように、該当丸にマウスオーバー時、在庫により、同時に変化されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2516328/5da39b2e-374f-fe23-343d-28d97c7ad1c5.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2516328/8ccdf9da-5499-26c9-8c8e-e7f119093d42.png)

今回の課題はbooleanタイプのonSaleを追加して、onSaleがtrueの時のみに'brand' + ' ' + 'product' + ' is on sale'を表示してみてください。

<details>
<summary>課題確認</summary><div>

```javascript:main.js
const app = Vue.createApp({
    data() {
        return {
            ...
            // solution
            onSale: true,
            ...
        }
    },
    methods: {
        ...
    },
    computed: {
      title() {
          // solution
          if(this.onSale) {
            return this.brand + ' ' + this.product + ' is on sale'
          } else {
            return this.brand + ' ' + this.product
          }
      },
      ...
    }
})

```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2516328/e23e6628-7dba-fb33-3101-d5648eb2dfec.png)

私は上記のようにやり、公式サイトの内容は以下のものです。

```javascript:main.js
const app = Vue.createApp({
    data() {
        return {
            ...
            // solution
            onSale: true,
            ...
        }
    },
    methods: {
        ...
    },
    computed: {
      title() {
          return this.brand + ' ' + this.product
      },
      ...
      // solution
      sale() {
          if (this.onSale) {
              return this.brand + ' ' + this.product + ' is on sale'
          }
          return ''
      }
    }
})

```

```html:index.html：saleを追記
            <h1>{{ title }}</h1>
            <!-- solution -->
            <p>{{ sale }}</p>
```

</div>
</details>