_index.js
單選框內(nèi)部一共有三個組件:el-radio
渺贤、el-radio-button
和el-radio-group
,我們將一一進行講解。
import Radio from './src/radio';
import RadioButton from './src/radio-button.vue';
import RadioGroup from './src/radio-group.vue';
export default function(Vue) {
Vue.component(Radio.name, Radio);
Vue.component(RadioButton.name, RadioButton);
Vue.component(RadioGroup.name, RadioGroup);
};
export { Radio, RadioButton, RadioGroup };
radio-group
radio-group
的實現(xiàn)十分簡單缰趋,就是一個div.radio-group
包裹著一個slot
捧杉。
<template>
<div class="el-radio-group">
<slot></slot>
</div>
</template>
script
包含一系列改變樣式的prop
陕见。
props: {
size: String, // Radio 按鈕組尺寸
fill: { // 按鈕激活時的填充色和邊框色
type: String,
default: '#20a0ff'
},
textColor: { // 按鈕激活時的文本顏色
type: String,
default: '#fff'
}
},
watch
上監(jiān)聽了value
,它會觸發(fā)change
事件并且向父組件傳遞el.form.change
事件味抖。
watch: {
value(value) {
this.$emit('change', value);
this.dispatch('ElFormItem', 'el.form.change', [this.value]);
}
}
其中dispatch
是從emitter
這一mixin
中引入的评甜,我們將在mixin篇
中進行講解,簡單的說仔涩,這是用來模擬vue1.0
中向父組件傳播事件的$dispatch
的忍坷。
mixins: [Emitter],
radio
radio
組件其實也先相對簡單,它同樣引入了emitter
這一mixin
熔脂,我們將按照從外往里的順序進行分析佩研。
label
首先最外面是一個label
標(biāo)簽作為包裹。
<label class="el-radio">
</label>
input
然后霞揉,是作為input
的span
部分旬薯,它包含一個用來表示選中效果的span
和一個不可以見的input
用來模擬原生的radio
。
最外層el-radio__input
最外層是span.el-radio__input
适秩,上面有一些動態(tài)class
绊序,來調(diào)整樣式,我們也將一一進行講解秽荞。
<span class="el-radio__input"
:class="{
'is-disabled': disabled,
'is-checked': model === label,
'is-focus': focus
}"
>
</span>
disabled
disabled
是一個簡單的Boolean
型的prop
骤公,會影響是否可以選中。
props:{
disabled: Boolean,
}
label
label
是radio
選中時的value
扬跋,也是通過prop
傳遞的阶捆。
props: {
label: {},
}
model
model
是一個計算屬性,也不是很復(fù)雜,就是用來實現(xiàn)v-model
的洒试。
computed: {
model: {
get() {
// 如果父組件是radio-group刊咳,返回父組件的value,否則返回自己的value
return this.isGroup ? this._radioGroup.value : this.value;
},
set(val) {
if (this.isGroup) {
// 如果父組件是 radio-group儡司,派發(fā)input事件娱挨,讓父組件去 emit input 事件
this.dispatch('ElRadioGroup', 'input', [val]);
} else {
// 否則自己 emit input 事件
this.$emit('input', val);
}
}
}
}
其中isGroup
是另一個計算屬性,用來一直向上尋找捕犬,看看有沒有父組件乃至祖先組件是radio-group
跷坝。
computed: {
isGroup() {
let parent = this.$parent;
while (parent) {
if (parent.$options.componentName !== 'ElRadioGroup') {
parent = parent.$parent;
} else {
this._radioGroup = parent;
return true;
}
}
return false;
},
}
focus
focus
是一個data
屬性,會在原生的input
的獲得焦點和失去焦點時被改變碉碉。
el-radio__inner
el-radio__inner
是用來實現(xiàn)選中效果的柴钻,通過css
控制。
<span class="el-radio__inner"></span>
input
最后是一個input
來模擬原生的radio
垢粮,上面進行了一些簡單的處理贴届,并綁定了相應(yīng)的數(shù)據(jù)。
<input
class="el-radio__original"
:value="label"
type="radio"
v-model="model"
@focus="focus = true"
@blur="focus = false"
:name="name"
:disabled="disabled">
radio-button
radio-button
和radio
基本上一樣蜡吧。
label
最外面仍然是一個label
毫蚓。
<label
class="el-radio-button"
:class="[
size ? 'el-radio-button--' + size : '',
{ 'is-active': value === label }
]"
>
</label>
size
size
是一個計算屬性,它直接使用了沿著父組件向上尋找到的radio-group
上設(shè)置的size
昔善。
computed: {
size() {
return this._radioGroup.size;
}
}
_radioGroup
也是一個計算屬性元潘,它將一直向上尋找radio-group
:
computed: {
_radioGroup() {
let parent = this.$parent;
while (parent) {
if (parent.$options.componentName !== 'ElRadioGroup') {
parent = parent.$parent;
} else {
return parent;
}
}
return false;
},
}
label
label
是一個prop
,用來表示選中該按鈕時的value
值君仆。
props: {
label: {},
}
value
value
是用來實現(xiàn)v-model
的翩概,來獲取選擇的按鈕,從其代碼可以看出來返咱,radio-button
和radio
不同钥庇,它不能脫離radio-group
單獨使用:
computed: {
value: {
get() {
return this._radioGroup.value;
},
set(value) {
this._radioGroup.$emit('input', value);
}
},
}
input
然后是用來模擬原生radio
的input
,上面綁定了相應(yīng)的數(shù)據(jù):
<input
class="el-radio-button__orig-radio"
:value="label"
type="radio"
v-model="value"
:name="name"
:disabled="disabled">
el_radio-button__inner
最后是真正會顯示的按鈕span
即其樣式咖摹,它內(nèi)部的值可以通過匿名的默認(rèn)slot
或者label
進行設(shè)置评姨,前者具有更高的優(yōu)先級:
<span class="el-radio-button__inner" :style="value === label ? activeStyle : null">
<slot></slot>
<template v-if="!$slots.default">{{label}}</template>
</span>
可以看出上面還綁定了一個動態(tài)的style
,它通過判斷value === label
決定當(dāng)前按鈕是否被選中楞艾,然后應(yīng)用activeStyle
参咙,而這個activeStyle
也是一個計算屬性,簡單的說它會根據(jù)父級radio-group
的屬性來設(shè)置樣式:
computed: {
activeStyle() {
return {
backgroundColor: this._radioGroup.fill,
borderColor: this._radioGroup.fill,
color: this._radioGroup.textColor
};
},
}