先看一下效果,注意:完全沒有使用任何表單控件
實(shí)現(xiàn)原理
在Vue中耕肩,我們一般都使用v-model來實(shí)現(xiàn)表單控件的雙向數(shù)據(jù)綁定那槽,但是一般而言我們都使用在表單控件上,例如input鳞芙,textarea;但是如果我們現(xiàn)在一般都不使用原生的表單樣式,因?yàn)樗鼘?shí)在是太太太丑了
其實(shí)我們是可以給組件設(shè)置v-model屬性的原朝,此時(shí)驯嘱,不論你的組件內(nèi)部是不是一個(gè)表單元素,你都可以使用v-model這個(gè)屬性
v-model其實(shí)是一個(gè)
value + input 以及 checked || selected + change
的語法糖喳坠,它在內(nèi)部做了一些事情鞠评,當(dāng)你給元素綁定v-model的時(shí)候,v-model會(huì)監(jiān)聽元素的input事件壕鹉,并且給元素設(shè)置一個(gè)value值那么我們就可以通過這個(gè)特性剃幌,來達(dá)到給組件使用v-model的方法
如文章開頭的gif圖所示,我制作的是一個(gè)單選按鈕組件晾浴,并沒有使用input负乡,所以按正常情況下我是不能直接使用v-model來控制這個(gè)組件的
父組件內(nèi)代碼示例,需要注意的是: @change并不是必須的脊凰,只是為了觸發(fā)某一個(gè)事件而定義的抖棘,你也可以使用watch監(jiān)聽對應(yīng)的值發(fā)生變化的時(shí)候做一些事情
<template>
<div class="home" align="center">
<my-radio label="a" v-model="check" @change="checkChange"/>
<my-radio label="b" v-model="check" @change="checkChange"/>
<my-radio label="c" v-model="check" @change="checkChange"/>
<b>當(dāng)前選中的是{{check}}</b>
<p></p>
<my-radio label="1" v-model="num" @change="checkChange"/>
<my-radio label="2" v-model="num" @change="checkChange"/>
<my-radio label="3" v-model="num" @change="checkChange"/>
<b>當(dāng)前選中的是{{num}}</b>
</div>
</template>
<script>
import myRadio from '../components/Home/myRadio';
export default {
name: 'home',
data() {
return {
check: 'a',
num: '1'
}
},
methods: {
checkChange(value) {
console.log(value)
}
},
components: {
myRadio
}
}
</script>
我們來看一下具體是怎么實(shí)現(xiàn)的吧
value 屬性,是必須的狸涌,我們之前說過了切省,在使用v-model的時(shí)候,它會(huì)給元素設(shè)置一個(gè)value值帕胆,當(dāng)我們使用的是一個(gè)input的時(shí)候朝捆,input原生支持value值,而當(dāng)我們使用的是一個(gè)組件的時(shí)候惶楼,我們可以通過props來接收一個(gè)value值
label 屬性右蹦,是必須的诊杆,為了能夠?qū)崿F(xiàn)單選按鈕歼捐,所以需要設(shè)置一個(gè)值來確保當(dāng)前按鈕什么時(shí)候被選中
<template>
<span class="my-radio">
<span
:class="['my-radio-container',{checked: value===label}]"
@click="clickRadio"
>
<span>{{ label }}</span>
</span>
</span>
</template>
<script>
export default {
name: "Radio",
props: {
value: {
type: [String, Number]
},
label: {
type: [String, Number]
}
},
methods: {
clickRadio() {
this.$emit('input', this.label);
this.$emit('change', this.label);
}
}
}
</script>
樣式文件,使用scss編寫晨汹,這個(gè)樣式文件你可以通過自己的喜好來編寫豹储,我為了實(shí)現(xiàn)效果,沒有做太多的樣式編寫
.my-radio {
display: inline-block;
&+.my-radio {
margin-left: 20px;
}
.my-radio-container {
display: inline-flex;
align-items: center;
span {
padding: 20px 40px;
font-size: 34px;
border: 1px solid #d9d9d9;
border-radius: 10px;
position: relative;
}
&.checked {
span {
color: #54d61e;
border-color: #54d61e;
position: relative;
overflow: hidden;
&:after {
content: '√';
right: 0;
top: 0;
position: absolute;
font-size: 20px;
width: 25px;
height: 25px;
background: #54d61e;
color: #fff;
}
}
}
}
}
結(jié)言
感謝您的查閱淘这,代碼冗余或者有錯(cuò)誤的地方望不吝賜教剥扣;菜鳥一枚,請多關(guān)照