從零實現Vue的元件庫(十四)- RadioGroup 實現
-
radio
與radioGroup
之間的聯動關係、資料繫結關係,使得radio
可以單獨使用或者組合; - 利用插槽可以方便擴充套件
radio
。
1. 例項

程式碼
<!-- 基礎用法 --> <fat-radio v-model="otherValue" :value="1"> <fat-hover-tip type="right-center"> <template slot="hover-part">あらがき ゆい</template> <template slot="tip-part"> <img src="/static/img/gakki.jpg" style="width: 100px" alt="示意圖"> </template> </fat-hover-tip> </fat-radio> <fat-radio v-model="otherValue" :value="2"> <fat-hover-tip type="right-center"> <template slot="hover-part">石原さとみ</template> <template slot="tip-part"> <img src="/static/img/u=4046980169,286278015&fm=26&gp=0.jpg" style="width: 100px" alt="示意圖" > </template> </fat-hover-tip> </fat-radio> <!-- 禁用狀態 --> <fat-radio-group v-model="anotherValue"> <fat-radio :value="1">備選項</fat-radio> <fat-radio :value="2" disabled>備選項</fat-radio> </fat-radio-group> 複製程式碼
例項地址:RadioGroup 例項
程式碼地址: Github UI-Library
2. 原理
Radio
首先單獨實現 Radio 元件,它是由 label
和 input
兩部分構成,主要區分兩個狀態, checked
以及 disabled
。
<template> <label class="radio" :class="[ { 'is-checked': value === model }, { 'is-disabled': isDisabled } ]" @click.stop="handleClick" > <!-- checked 時展示被選中狀態 --> <span class="radio-inner"></span> <input class="f-hide" type="radio" :disabled="isDisabled" v-bind="$attrs" :value="model" @click.stop > <!-- 提示文案(可插入元件) --> <slot></slot> </label> </template> <script> export default { props: { value: { type: [String, Number], required: true }, disabled: { type: [Boolean], default: false }, propValue: { type: [String, Number] } }, model: { prop: "propValue", event: "select" }, computed: { isGroup() { return this.$parent.$options._componentTag === "fat-radio-group"; }, isDisabled() { return this.$parent.disabled || this.disabled; }, model: { get() { return this.isGroup ? this.$parent.value : this.propValue; }, set(newValue) { this.isGroup ? this.$parent.$emit("select", newValue) : this.$emit("select", newValue); } } }, methods: { handleClick(event) { !this.isDisabled && (this.model = this.value); } } }; </script> 複製程式碼
由於需要實現 Radio
可以單獨使用的,所以不採用 provide / inject
api,而是利用 this.$parent.$options._componentTag
判斷,當前元件是否為 Group
。同時實現資料的傳遞
model: { get() { return this.isGroup ? this.$parent.value : this.propValue; }, set(newValue) { this.isGroup ? this.$parent.$emit("select", newValue) : this.$emit("select", newValue); } } 複製程式碼
同樣,也是依據 isGroup
進行區分,來選擇是 $emit
父元件還是子元件。
RadioGroup
則是在 Radio 的外部包裹一層 Group 用於,實現組的概念
<template> <div :class="[ 'radio-group' ]" name="radio-group"> <slot></slot> </div> </template> <script> export default { name: "radio-group", props: { value: { type: [String, Number] }, disabled: { type: Boolean } }, model: { prop: "value", event: "select" }, watch: { value(newValue) { this.$emit("change", newValue); } } }; 複製程式碼