その他のディレクレィブ 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
を作成する。
はじめにラジオボタンの項目を詰めたオブジェクトに型名をつけておく。
export interface RadioAlternative {
value: string;
alternative: string;
}
前回学んだことと組み合わせると親コンポーネントから配列を受け取り、v-forでラジオボタンを配置して選択が変更されるたびに親にEmitすることができる。
<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>
<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-else
とv-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-if
とv-show
の使い分けは表示を切り替える頻度を参考にする。
切り替えの頻度が低ければv-if
切り替えの頻度が高ければv-show
というのもv-show
はDOM自体は保持しているが、CSSで表示をオフにしているだけなので、表示/非表示を何度も切り替えても描画コストが低い。一方で、v-if
はfalse
であれば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
}