![見出し画像](https://assets.st-note.com/production/uploads/images/54711777/rectangle_large_type_2_de5d9044bee45acfb7b6e08dfbf8dd9d.png?width=1200)
【Nuxt.js】input type="checkbox"をコンポーネント化する時のパターン
🎈 WPでも公開中です
https://wp.me/pc9NHC-1l0
前置き
input type="checkbox"
チェックボタン部分のみを
コンポーネントにする時のコードを
書いています✍
シュガーシンタックス
v️-modelのおさらいから
実際のコンポーネントの
サンプルコードなどを
載せていきます🍀
参考:
Checkbox の Vue コンポーネントを作成する Tips
【Vue.js 再入門】 v-model を正しく理解して親子間コンポーネントのデータ伝播をマスターする
【Vue】Input内の値をv-modelのように親子間でバインドさせる方法【サンプルあり】
【Nuxt.js】ネストしたコンポーネントでv-modelの変更を親に反映させる
【Nuxt.js】フォームをコンポーネント化した時のメモ(子Componentで変更されたv-modelの値を親に反映する)
おさらい
v-modelはシュガーシンタックス
v-bind:value, v-on:input
これらを簡単に書けるものでした🌟
<template>
<input
type="text"
:value="value"
@input="$emit('input', $event.target.value)"
>
</template>
<script lang="ts">
export default {
props: {
value: {
type: String,
default: 'ハロー'
}
},
}
</script>
この例はtype="text"ですが、
それぞれのtypeや
入力タグに合わせた
属性のバインディング
そしてイベントにしてくれます💡
・type="input", textareaタグは:valueと@input
・type="checkbox", type="radio"は:checkedと@change
・selectタグは:valueと@change
今回はチェックボックスなので
:checkedと@changeですね💡
パターン1: 定番
まずは定番の型。
おさらいでやった
type="text"を
type="checkbox"
バージョンにしただけです。
@inputでも動きますが、
意味的にも@changeが良いですね🍀
<template>
<label class="label">
<input
type="checkbox"
:checked="checked"
@change="$emit('input', $event.target.checked)"
/>
</label>
</template>
<script>
export default {
props: {
checked: {
type: Boolean,
default: false,
},
},
}
</script>
<template>
<div class="page">
<InputCheckbox v-model="isChecked" />
<p>{{ isChecked }}</p>
</div>
</template>
<script>
export default {
data() {
return {
isChecked: '',
}
},
}
</script>
##デザインカスタムをするなら…
inputのデザインは変えられないため、
inputを見えないようにし、
spanで装飾をする必要がありますね💫
それを踏まえるとこんな感じ💡
<template>
<label class="label">
<input
class="input"
type="checkbox"
:checked="checked"
@input="$emit('input', $event.target.checked)"
/>
<span class="mark"></span>
<span class="text">{{ text }}</span>
</label>
</template>
</template>
<script>
export default {
props: {
checked: {
type: Boolean,
default: false,
},
text: {
type: String,
default: '',
},
},
}
</script>
<style lang="scss" scoped>
.label {
padding: 12px 8px;
display: flex;
align-items: center;
cursor: pointer;
&:hover > .mark {
background: #dddddd !important;
border: solid 2px #008eff;
}
.input {
margin: 0;
width: 0;
opacity: 0;
}
.input:focus + .mark {
background: #dddddd !important;
border: solid 2px #008eff;
}
.input:checked + .mark {
border: solid 2px #008eff;
background: #ffffff;
}
.input:checked + .mark::before {
content: '';
display: block;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -45%);
width: 80%;
height: 80%;
background: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path fill="%23008EFF" d="M20.285 2l-11.285 11.567-5.286-5.011-3.714 3.716 9 8.728 15-15.285z"/></svg>')
no-repeat center;
background-size: contain;
}
.mark {
position: relative;
top: 0;
left: 0;
display: block;
width: 32px;
height: 32px;
border: solid 2px #93cfff;
background: #ffffff;
border-radius: 4px;
}
.text {
margin-left: 12px;
display: block;
font-size: 18px;
font-weight: bold;
}
}
</style>
<template>
<div class="page">
<InputCheckbox v-model="isChecked" text="同意する" />
{{ isChecked }}
</div>
</template>
<script>
export default {
data() {
return {
isChecked: '',
}
},
}
</script>
パターン2: 子でv-model
親でv-modelはあっても
子でv-modelって
全然見たことないですよね?👀
子でチェックのON/OFFを
まとめて管理できるので、
使えると良いな〜😀💭
と思っていたら、
コードを書いてる記事を発見✨🔍
こんな感じです🍀
<template>
<label>
<input type="checkbox" v-model="inputedValue" />
{{ checked }}
</label>
</template>
<script>
export default {
model: {
prop: 'checked',
event: 'change',
},
props: {
checked: {
type: Boolean,
},
},
computed: {
inputedValue: {
get() {
return this.checked
},
set(newValue) {
this.$emit('change', newValue)
},
},
},
}
</script>
<template>
<div class="page">
<InputCheckbox v-model="checked" />
</div>
</template>
<script>
export default {
data() {
return {
checked: '',
}
},
}
</script>
なんと親でも子でもv-model❗️笑
どういうこと❓と思っていたら
scriptに見慣れない
modelというものがありました。
Vueの公式を探して発見🔍
#model
こんな使い方もあるんですね…✨👏
参考:
【Nuxt.js】ネストしたコンポーネントでv-modelの変更を親に反映させる
【Vue.js 再入門】 v-model を正しく理解して親子間コンポーネントのデータ伝播をマスターする
【Nuxt.js】フォームをコンポーネント化した時のメモ(子Componentで変更されたv-modelの値を親に反映する)
そういえばVue3の変更点は
なんだったけな〜と思っていたら、
同じ箇所で複数使用できる、でした。
やりたいこととは違いますが、
備忘録的に残しておきます🌟
Vue3でv-modelがどう変わったか
##これはNG
パッと思いついて
やりがちなのは、
v-modelの値をpropsで
親から渡す…
こんな感じではないでしょうか。
<template>
<label>
<input type="checkbox" v-model="checked" />
</label>
</template>
<script>
export default {
props: ['checked'],
}
</script>
<template>
<div class="page">
<InputCheckbox checked="true" />
</div>
</template>
しかしこれだと
「読み書き」の「読み」
しかできないんです。
実際、チェックを触らなければ
エラーはないのですが、
つけ外しを行うとエラーになります💥✋
まとめ
form要素のコンポーネントを
パターン化しておきたいな〜
と思って今回はcheckboxに✍
type="text"以外は
結構ややこしくて
苦戦しています😵💦笑
でもこれが理解できたら
すごく便利だし、
form要素ってinputのtypeも
他のタグも入れたら結構あるし、
コンポーネントにして
スッキリ分けたいじゃないですか…🧹
なので各要素の記事と、
各要素の良いコードを抜粋して
全部を一覧で見れる記事を
書こうと思っています…🎈🧸
🎈 WPでも公開中です
https://wp.me/pc9NHC-1l0
この記事が気に入ったらサポートをしてみませんか?