Vue.jsで親要素から子要素に渡す画像URLから画像を表示する(初心者の自分用まとめ)
単一データを渡して画像を表示する
ポイント
- 親側で、dataに画像URLを含むデータを定義しておく
- 子側で、受け取ったUrlを入れ込んで、
styleObject
を作り、style
属性をv-bind
で紐づけることで、背景画像として表示させる
ポイント整理図
ソース(親側)
<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する文を書き込んでいる。
ポイント整理図
ソース(親側)
<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の回答を参考にしたのですが、この一見みんなが忌避しそうなベタ書きを採用している人は案外少なくないようで、妥当性はあるのかなと思います。
もし、もっとスマートなやり方をご存知の方がいましたら、コメント書き込みいただけると嬉しいです。 自分でも見つけ次第追記しようと思います。