公式ホームページのIntro to Vue 3クラス7 (Class & Style Binding)

# 7. Class & Style Binding

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

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

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

今日のポイントはアップデータに基づいてクラスとスタイルのバインドを行うことです。

```javascript:main.js
const app = Vue.createApp({
    data() {
        return {
            cart:0,
            product: 'Socks',
            brand: 'Vue Mastery',
            image: './assets/images/socks_blue.jpg',
            inStock: false,
            details: ['50% cotton', '30% wool', '20% polyester'],
            variants: [
              { id: 2234, color: 'green', image: './assets/images/socks_green.jpg' },
              { id: 2235, color: 'blue', image: './assets/images/socks_blue.jpg' },
            ]
        }
    },
    methods: {
        addToCart() {
            this.cart += 1
        },
        updateImage(variantImage) {
            this.image = variantImage
        }
    }
})


```

```html:index.html
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>Vue Mastery</title>
    <!-- Import Styles -->
    <link rel="stylesheet" href="./assets/styles.css" />
    <!-- Import Vue.js -->
    <script src="https://unpkg.com/vue@3.0.11/dist/vue.global.js"></script>
  </head>
  <body>
    <div id="app">
      <div class="nav-bar"></div>

      <div class="cart">Cart({{ cart }})</div>
      
      <div class="product-display">
        <div class="product-container">
          <div class="product-image">
            <img v-bind:src="image">
          </div>
          <div class="product-info">
            <h1>{{ product }}</h1>
            <p v-if="inStock">In Stock</p>
            <p v-else>Out of Stock</p>
            <ul>
              <li v-for="detail in details">{{ detail }}</li>
            </ul>

            <div 
              v-for="variant in variants" 
              :key="variant.id" 
              @mouseover="updateImage(variant.image)"
            >{{ variant.color }}</div>
            <button class="button" @click="addToCart">Add to Cart</button>
          </div>
        </div>
      </div>
    </div>

    <!-- Import App -->
    <script src="./main.js"></script>

    <!-- Mount App -->
    <script>
      const mountedApp = app.mount('#app')
    </script>
  </body>
</html>

```
## スタイルバインド
greenやblueの文字を各色の丸として表示して、それにマウスオーバー時に靴下の色が変わるようにやりましょう。
まずは、variantのdivに下記のようにcolor-circleクラスを追記して、styleをバインドするために:styleとして、追記します。
:styleへ変更することにより、内部はjavascriptになります。それで、スタイルの属性名がcamelCaseにするか、''に囲めて書く必要があります。他には全体のバインドも可能です。

```html:index.html
:style="{ backgroundColor: variant.color }"
<!-- 又は -->
:style="{ 'background-color': variant.color }"
<!-- 又は -->
:style="styles"
```

```javascript:main.js
const app = Vue.createApp({
    data() {
        return {
            ...
            styles: {
               color: 'red',
               fontSize: '14px'
            }
        }
    },
    methods: {
        ...
    }
})


```
その後に、内部の「{{ variant.color }}」を削除します。

```html:index.html
            <div 
              v-for="variant in variants" 
              :key="variant.id" 
              @mouseover="updateImage(variant.image)"
              class="color-circle"
              :style="{ backgroundColor: variant.color }"
            ></div>
            <button class="button" @click="addToCart">Add to Cart</button>
          </div>
```
style.cssはassetsフォルダは以下にあります。color-circleは既にあるので、何もやる必要はないです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2516328/9c7e3ebb-fca3-847b-5ab5-ea654193de58.png)

```css:style.css
.color-circle {
  width: 50px;
  height: 50px;
  margin-top: 8px;
  border: 2px solid #d8d8d8;
  border-radius: 50%;
}
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2516328/a00f64da-eeec-ebbf-6d08-688a42319d27.png)

## クラスバインド
inStockデータがfalseの場合には「Add to Cart」を非活性化表示して、trueの場合には「Add to Cart」を活性化表示して見ます。

```html:index.html
<button class="button" @click="addToCart">Add to Cart</button>
```

```html:index.html：disabled追記
<button class="button" :disabled="!inStock" @click="addToCart">Add to Cart</button>
```
見た目も活性化による区分ができるようにやります。

```css:style.css
.disabledButton {
  background-color: #d8d8d8;
  cursor: not-allowed;
}
```

```html:index.html：class追記
<button class="button" :class="{ disabledButton: !inStock }" :disabled="!inStock" @click="addToCart">Add to Cart</button>
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2516328/43bb1817-e50c-65da-efb0-a20b9640e8a0.png)

条件でやるクラスと固定のクラスを両方する場合は下記のように結合され、適応されます。

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


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

```javascript:main.js：activeClass追記
const app = Vue.createApp({
    data() {
        return {
            ...
            activeClass: true
        }
    },
    methods: {
        ...
    }
})


```
レンダリング後は下記のものになります。

```html:index.html
<div class="color-circle active"></div>
```

## 三項演算子

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

```html:index.html：三項演算子追記
            <div 
              v-for="variant in variants" 
              :key="variant.id" 
              @mouseover="updateImage(variant.image)"
              class="color-circle"
              :class="[ isActive? activeClass : '' ]"
              :style="{ backgroundColor: variant.color }"
            ></div>
```

```javascript:main.js：isActive追記
const app = Vue.createApp({
    data() {
        return {
            ...
            isActive: true
        }
    },
    methods: {
        ...
    }
})


```

今回の課題はinStockがfalseの場合、商品イメージにout-of-stock-imgクラスをバインドして見たください。

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

```javascript:main.js
const app = Vue.createApp({
    data() {
        return {
            cart:0,
            product: 'Socks',
            brand: 'Vue Mastery',
            image: './assets/images/socks_blue.jpg',
            inStock: false,
            details: ['50% cotton', '30% wool', '20% polyester'],
            variants: [
              { id: 2234, color: 'green', image: './assets/images/socks_green.jpg' },
              { id: 2235, color: 'blue', image: './assets/images/socks_blue.jpg' },
            ]
        }
    },
    methods: {
        addToCart() {
            this.cart += 1
        },
        updateImage(variantImage) {
            this.image = variantImage
        }
    }
})

```

```html:index.html
            <!-- solution -->
            <img :class="{ 'out-of-stock-img': !inStock }" v-bind:src="image">　　
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2516328/de40d4e2-bdc7-e83b-2cbd-1ae6e41cefd0.png)

</div>
</details>