経緯
まずはじめに、私はVue.js初心者です。
ラジオボタンで選択したものを後から出てくるコンテンツでテキストを切り替えて表示したく、
かつ、タイトルのコンポーネント内で表示したいという時につまずき、いろいろ模索した結果解決出来たので、
ちょっと細かく残しておきます。
まず、コンポーネントで親から子へデータをもたせるとき
(タイトルのコンポーネント)
親のテンプレート
<com-child title-text="タイトルを表示する">コンテンツ内容</com-child>
子コンポーネント
Vue.component('com-child',{
template: '<section><h1>{{ titleText }}</h1><slot></slot></section>',
props: ['titleText']
})
実際の表示
<section><h1>タイトルを表示する</h1>コンテンツ内容</section>
ここで使われているものを簡単に説明
- component:同じHTML構造を繰り返し使える機能
- props:親で定義した属性を子のtemplate内で使うことができる(ケバブケースとキャメルケースが混ざることに注意)
- slot:親のコンテンツを子のテンプレートに反映させる
やりたかったけど、できなかったこと
<input type="radio" value="赤" v-model="selectColor">
<input type="radio" value="青" v-model="selectColor">
<com-child title-text="あなたが{{ selectColor }}から連想するものはなんですか?">コンテンツ内容</com-child>
このような感じで、選択したものを次のタイトルに表示したかったが、
これでは、{{ selectColor }}
の部分がそのまま表示されてしまう
解決方法
v-bind
ディレクティブを使う。
<com-child v-bind:title-text="'あなたが' + selectColor + 'から連想するものはなんですか?'">コンテンツ内容</com-child>
これで、私がやりたかったことはできました。
赤を選択した時には、タイトルは「あなたが赤から連想するものはなんですか?」となります。
ちなみに、
<com-child title-text="'あなたが' + selectColor + 'から連想するものはなんですか?'">コンテンツ内容</com-child>
では、「'あなたが' + selectColor + 'から連想するものはなんですか?'」と表示されてしまいます。
ポイントとなるのは、属性
かv-bind
かです。
属性
とv-bind
子コンポーネントにprops
を定義しておけば、コンポーネントの呼び出し時に属性
にアクセスすることができます。
v-bind
は属性に対して埋め込みたい時に使います。
<a href="{{ url }}">リンク</a>
上記では正しく動きません。
<a v-bind:href="url">リンク</a>
これが正しいです。
ちなみに、v-bind
は省略できるので、以下でも同じです。
<a :href="url">リンク</a>
※ここの部分がきちんと理解できてなかった
- 属性値は文字列扱いとなる。
- 数値として値を渡したい場合は
v-bind:your-name="1"
のように表す - v-bindで文字列を渡す場合は、
v-bind:your-name="'山田'"
のようにダブルクォートの中をシングルクォートでくくる
今回の場合は、属性の中にテキスト以外も含まれていたので、v-bind
を使い、テキストの部分はシングルクォートでくくり、+
で連結することで解決できました。
最後に
挙動が確認できるコードを載せておきます。
<div id="app">
<com-child title-text="好きな色はなんですか?">
<input type="radio" value="赤" v-model="selectColor">赤
<input type="radio" value="青" v-model="selectColor">青
</com-child>
<com-child v-bind:title-text="'あなたが' + selectColor + 'から連想するものはなんですか?'">
<template v-if="selectColor === '赤'">
<input type="radio" value="りんご" v-model="selectThing">りんご
<input type="radio" value="ポスト" v-model="selectThing">ポスト
</template>
<template v-if="selectColor === '青'">
<input type="radio" value="空" v-model="selectThing">空
<input type="radio" value="サファイア" v-model="selectThing">サファイア
</template>
</com-child>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.min.js"></script>
Vue.component('com-child',{
template: '<section><h1>{{ titleText }}</h1><slot></slot></section>',
props: ['titleText']
})
new Vue({
el: '#app',
data: {
selectColor: '',
selectThing: ''
}
})