LoginSignup
15
10

More than 5 years have passed since last update.

Vue.jsで属性かv-bindかの応用

Last updated at Posted at 2018-11-15

経緯

まずはじめに、私は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: ''
  }
})
15
10
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
15
10