RadioGroup 元件的難點在於:基於 元件進行二次封裝的 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-item',
{ '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);
}
}
};
複製程式碼
3. 總結
RadioGroup 元件的開發,主要是父子元件之間的資料傳遞以及相關的結構分離。
往期文章:
- 從零實現Vue的元件庫(零)- 基本結構以及構建工具
- 從零實現Vue的元件庫(一)- Toast 實現
- 從零實現Vue的元件庫(二)- Slider 實現
- 從零實現Vue的元件庫(三)- Tabs 實現
- 從零實現Vue的元件庫(四)- File-Reader 實現
- 從零實現Vue的元件庫(五)- Breadcrumb 實現
- 從零實現Vue的元件庫(六)- Hover-Tip 實現
- 從零實現Vue的元件庫(七)- Message-Box 實現
- 從零實現Vue的元件庫(八)- Input 實現
- 從零實現Vue的元件庫(九)- InputNumber 實現
- 從零實現Vue的元件庫(十)- Select 實現
- 從零實現Vue的元件庫(十一)- Date-picker 實現
- 從零實現Vue的元件庫(十二)- Table 實現
- 從零實現Vue的元件庫(十三)- Pagination 實現
- 從零實現Vue的元件庫(十四)- RadioGroup 實現
- 從零實現Vue的元件庫(十五)- CheckboxGroup 實現
原創宣告: 該文章為原創文章,轉載請註明出處。