はじめに
おしゃれなフォームコントロールつくりたいですよね?
2.2.0から追加されたmodelオプション(API — Vue.js)を使えば、ビルトインのフォームコントロールを使う場合と同じようにv-modelディレクティブを利用できるようになります。
主要なフォームコントロールについて、簡単にカスタムコンポーネントをつくってみました。
<input type="text">
<template>
<input type="text" v-model="internalValue">
</template>
<script>
export default {
model: {
prop: "value",
event: "input"
},
props: {
value: {
type: String,
default: ""
}
},
computed: {
internalValue: {
get() {
return this.value;
},
set(val) {
this.$emit("input", val);
}
}
}
};
</script>
<input type="checkbox">
<template>
<label>
<input type="checkbox" v-model="internalValue">
{{ text }}
</label>
</template>
<script>
export default {
model: {
prop: "value",
event: "change"
},
props: {
value: {
type: Boolean,
default: false,
},
text: {
type: String,
default: ""
}
},
computed: {
internalValue: {
get() {
return this.value;
},
set(val) {
this.$emit("change", val);
}
}
}
};
</script>
<input type="radio">
<template>
<label>
<input type="radio" v-model="internalValue" :value="value">
{{ text }}
</label>
</template>
<script>
export default {
model: {
prop: "checked",
event: "change"
},
props: {
checked: {
type: String,
default: ""
},
text: {
type: String,
default: ""
},
value: {
type: String,
default: ""
}
},
computed: {
internalValue: {
get() {
return this.checked;
},
set(val) {
this.$emit("change", val);
}
}
}
};
</script>
<select>
select要素の場合、カスタムはul,liなどを利用するかもしれませんね。
<template>
<select v-model="selected">
<option v-for="option in options" :value="option.value" :key="option.value">{{ option.text }}</option>
</select>
</template>
<script>
export default {
model: {
prop: "value",
event: "change"
},
props: {
value: {
type: String,
default: ""
},
options: {
type: Array,
default() {
return [];
}
}
},
computed: {
selected: {
get() {
return this.value;
},
set(val) {
this.$emit("change", val);
}
}
}
};
</script>
デモ
簡単に動作確認ができるページを用意しました。
<template>
<div class="wrapper">
<div>
<custom-input v-model="valueA"/>
<p>result: {{ valueA }}</p>
</div>
<div>
<custom-checkbox v-model="valueB" text="checkbox"/>
<p>result: {{ valueB }}</p>
</div>
<div>
<custom-radio v-model="valueC" value="1" text="[1]"/>
<custom-radio v-model="valueC" value="2" text="[2]"/>
<p>result: {{valueC}}</p>
</div>
<div>
<custom-select
v-model="valueD"
:options="[{value: 'a', text: 'A'}, {value: 'b', text: 'B'}]"
/>
<p>result: {{ valueD }}</p>
</div>
</div>
</template>
<script>
import CustomInput from "./components/CustomInput";
import CustomSelect from "./components/CustomSelect";
import CustomRadio from "./components/CustomRadio";
import CustomCheckbox from "./components/CustomCheckbox";
export default {
data() {
return {
valueA: "",
valueB: false,
valueC: "1",
valueD: "a"
};
},
components: {
CustomInput,
CustomSelect,
CustomRadio,
CustomCheckbox
}
};
</script>