0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

簡単なForm作成から学ぶVue(TypeScript)の書き方 その3

Posted at

その他のディレクレィブ etc

〜contents〜

  • v-for
  • v-if v-else v-else-if
  • v-show
  • 算術プロパティ

RadioButtonコンポーネントから学ぶv-forディレクティブ

フォームの性別選択のラジオボタンを作ってみる。

v-forディレクティブは、オブジェクトや配列を受け取り、エイリアスを用いて各要素にアクセスできる。

構文
<div v-for="item in items">
  {{item.attr}}   //itemsの一要素を取得できる。
</div>

今回はラジオボタンの項目をリストで受け取りその項目数forループでラジオボタンを表示する。
componentsディレクトリ下にRadioButton.vueを作成する。

はじめにラジオボタンの項目を詰めたオブジェクトに型名をつけておく。

components/RadioAlternative.ts
export interface RadioAlternative {
  value: string;
  alternative: string;
}

前回学んだことと組み合わせると親コンポーネントから配列を受け取り、v-forでラジオボタンを配置して選択が変更されるたびに親にEmitすることができる。

親コンポーネント(Form)
<template>
  <div>
    <RadioButton :alts="sexList" name="sex" @updateSelected="updateSelected" />
  </div>
</template>

<script lang="ts">
import { Component, Vue } from 'vue-property-decorator';
import RadioButton from '@/components/RadioButton.vue'
import { RadioAlternative } from '@/components/RadioAlternative'

@Component({
  components:{
    RadioButton
  }
})
export default class Form extends Vue {
  private readonly sexList: Array<RadioAlternative> = [
    {
      value: "male",
      alternative: ""
    }, {
      value: "female",
      alternative: ""
    }
  ]

  private updateSelected(selected: string){
    console.log("parent:" + selected)
  }
}
</script>
子コンポーネント(RadioButton)
<template>
  <div>
    <span v-for="alt in alts" :key="alt.value">
      <label><input type="radio" :name="name" :value="alt.value" @change="changeSelected" >{{alt.alternative}}</label>
    </span>
  </div>
</template>

<script lang="ts">
import { Component, Prop, Vue, Emit } from 'vue-property-decorator';
import { RadioAlternative } from './RadioAlternative'

@Component
export default class TextBox extends Vue {
  private alt: RadioAlternative

  @Prop()
  private alts: Array<RadioAlternative>

  @Prop()
  private name: string

  private changeSelected() :void {
    if (event!.target instanceof HTMLInputElement) {
      console.log(event!.target.value)
      this.updateSelected(event!.target.value)
    }
  }

  @Emit('updateSelected')
  private updateSelected(selected: string): void{
  }
}
</script>

この場合初めからどちらかを選択した状態にするcheckedはつけられないのだろうか。。

コンテンツの表示/非表示を切り替える条件分岐

ラジオボタンの選択に応じて表示するコンテンツを変更する機能を実装する。
今回は上のラジオボタンで性別により異なるコンテンツが表示されるように分岐してみる。

  • v-if
  • v-show

v-ifディレクティブ

v-ifディレクティブは値がtrueであれば表示、falseであれば非表示とするもの。
v-elsev-else-ifもだいたい予想がつく通り。なお、v-ifの直後に配置しないと認識されない。

<template>
  <div>
    <RadioButton :alts="sexList" name="sex" @updateSelected="updateSelectedSex" />
    <div v-if="sex === 'male'">**ここに何かしらのコンテンツ**</div>
    <div v-else>**何か別のコンテンツ**</div>
  </div>
</template>

<script lang="ts">
import { Component, Vue } from 'vue-property-decorator';
import RadioButton from '@/components/RadioButton.vue';
import { RadioAlternative } from '../components/RadioAlternative';

@Component({
  components:{
    RadioButton
  }
})
export default class Form extends Vue {
  private readonly sexList: Array<RadioAlternative> = [
    {
      value: "male",
      alternative: ""
    }, {
      value: "female",
      alternative: ""
    }
  ]

  private sex: string = ""

  private updateSelectedSex(selected: string){
    console.log("parent:" + selected)
    this.sex = selected
  }
}
</script>

v-showディレクティブ

v-showは同じく値がtrueの時のみ表示し、falseでは非表示とするもの。
こちらは分岐させることはできない。

    <div v-if="sex === 'male'">**ここに何かしらのコンテンツ**</div>

v-ifv-showの使い分けは表示を切り替える頻度を参考にする。

切り替えの頻度が低ければv-if
切り替えの頻度が高ければv-show

というのもv-showはDOM自体は保持しているが、CSSで表示をオフにしているだけなので、表示/非表示を何度も切り替えても描画コストが低い。一方で、v-iffalseであればDOM自体が消失するため、表示切り替えをするたびにDOMを構成し直す必要があり、描画コストが高い。そのため、何度も表示/非表示が切り替わるようなコンテンツには不向きである。

算術プロパティ

上記の例では表示の条件判定の際に条件式sex === 'male'を直接書き込んでいた。
しかし、もし、条件が複雑となった場合、この一行に記述するのはひどく可読性を損なう。
そこで、算術プロパティを使用する。

算術プロパティは関数のように記述し、内部で使用するデータ(変数)の値が変更されると勝手に再計算され、値がreturnされる。計算結果をreturnするgetterのようなものと考える。
なお、一般の関数methodと異なる点は、算術プロパティは内部のデータに変更があるまでは以前の値をキャッシュし、それをreturnし続ける点である。

注意点としては初期化されていない変数は追跡されない(変更が検出されない)こと。算術プロパティ内部に分岐処理があり初期の経路では通らない処理にのみ置かれた変数も同様に追跡の対象とならない。

jsではComputed:として記述される。

    <div v-if="isMale">**ここに何かしらのコンテンツ**</div>
親コンポーネントに追記
  private get isMale(): boolean{
    if (this.sex === "male")
      return true
    else
      return false
  }
0
0
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
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?