鶏口牛後な日々

魔法使い(なんでも作れるエンジニア)を目指してます。ブログは発散中

Vue.jsで親要素から子要素に渡す画像URLから画像を表示する(初心者の自分用まとめ)

単一データを渡して画像を表示する

ポイント

  • 親側で、dataに画像URLを含むデータを定義しておく
  • 子側で、受け取ったUrlを入れ込んで、 styleObject を作り、 style 属性を v-bind で紐づけることで、背景画像として表示させる

ポイント整理図 f:id:TACOSVilledge:20181102162156j:plain

ソース(親側)

<template lang="pug">
    ProductCard(v-bind:product="product")
</template>

import ProductCard from '/path/productCard.vue';

<script>
export default {
  name: 'ImageShow',
  components: {
    ProductCard
  },
  data () {
    return {
      product: {
        productId: '1',
        productName: 'carrot cake',
        imageUrl: '/path/image1.png'
      }
    }
  }
}
</script>

注:ProductCard は子コンポーネントの名前。

ソース(子側)

<template lang="pug">
  .product-img(:style="styleObject")
</template>

<script>
export default {
  props: {
    product: {
      type: Object
    }
  },
  data () {
    return {
      styleObject: {
        'background-image' : `url(${this.product.imageUrl})`
       }
    }
  }
}
</script>

親要素から渡すデータが複数で、v-forを使って表示する場合

ポイント

  • 子側では、style属性に直接bindする文を書き込んでいる。

ポイント整理図 f:id:TACOSVilledge:20181102162203j:plain

ソース(親側)

<template lang="pug">
    ProductCard(v-bind:products="products")
</template>

import ProductCard from '/path/productCard.vue';

<script>
export default {
  name: 'ImageShow',
  components: {
    ProductCard
  },
  data () {
    return {
      products: [
        {
          productId: '1',
          productName: 'carrot cake',
          imageUrl: '/path/image1.png'
        },
        {
          productId: '2',
          productName: 'spinach cookie',
          imageUrl: '/path/image2.png'
        }
      ] 
    }
  }
}
</script>

ソース(子側)

<template lang="pug">
div(v-for="product in products")
  .product-img(
     v-bind:style=" {
       'background-image': 'url(' + product.imageUrl + ')'
     }"
  )
</template>

<script>
export default {
  props: {
    products: {
      type: Array
    }
  }
}
</script>

なぜ単一データを渡す場合と同様に、 styleObject を定義しておき、 style 属性を紐づける形ではできないか?

おそらくできるのだと思う。 色々と痒いところに手が届くVue.jsで、それができないなんてことはないと思うのです。 ただ、私ができなかったので一旦このような形で書いています。

と言いますのは、子側のdata() 内で、 styleObject を定義しようとするとき、この文の中では、 props として定義している要素(この例では、 products )は使うことができますが、その1つ1つの要素(つまり単数の product)にはアクセスができないのです。 HTML内では、 v-for の中で、 v-for="product in products と定義しているため、個々の要素にアクセスできるわけですが、これができなかったのです。

そのため、 v-for を指定した要素の子要素に、直接的に product.imageUrl を書き込むためにこのような書き方をしました。

この書き方は、stackoverflowの回答を参考にしたのですが、この一見みんなが忌避しそうなベタ書きを採用している人は案外少なくないようで、妥当性はあるのかなと思います。

もし、もっとスマートなやり方をご存知の方がいましたら、コメント書き込みいただけると嬉しいです。 自分でも見つけ次第追記しようと思います。