Element分析(元件篇)——Radio
_index.js
單選框內部一共有三個元件: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
的實現十分簡單,就是一個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
上監聽了value
,它會觸發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
標籤作為包裹。
<label class="el-radio">
</label>
input
然後,是作為input
的span
部分,它包含一個用來表示選中效果的span
和一個不可以見的input
用來模擬原生的radio
。
最外層el-radio__input
最外層是span.el-radio__input
,上面有一些動態class
,來調整樣式,我們也將一一進行講解。
<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
是一個計算屬性,也不是很複雜,就是用來實現v-model
的。
computed: {
model: {
get() {
// 如果父元件是radio-group,返回父元件的value,否則返回自己的value
return this.isGroup ? this._radioGroup.value : this.value;
},
set(val) {
if (this.isGroup) {
// 如果父元件是 radio-group,派發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
是用來實現選中效果的,通過css
控制。
<span class="el-radio__inner"></span>
input
最後是一個input
來模擬原生的radio
,上面進行了一些簡單的處理,並繫結了相應的資料。
<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
上設定的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
是用來實現v-model
的,來獲取選擇的按鈕,從其程式碼可以看出來,radio-button
和radio
不同,它不能脫離radio-group
單獨使用:
computed: {
value: {
get() {
return this._radioGroup.value;
},
set(value) {
this._radioGroup.$emit('input', value);
}
},
}
input
然後是用來模擬原生radio
的input
,上面繫結了相應的資料:
<input
class="el-radio-button__orig-radio"
:value="label"
type="radio"
v-model="value"
:name="name"
:disabled="disabled">
el_radio-button__inner
最後是真正會顯示的按鈕span
即其樣式,它內部的值可以通過匿名的預設slot
或者label
進行設定,前者具有更高的優先順序:
<span class="el-radio-button__inner" :style="value === label ? activeStyle : null">
<slot></slot>
<template v-if="!$slots.default">{{label}}</template>
</span>
可以看出上面還繫結了一個動態的style
,它通過判斷value === label
決定當前按鈕是否被選中,然後應用activeStyle
,而這個activeStyle
也是一個計算屬性,簡單的說它會根據父級radio-group
的屬性來設定樣式:
computed: {
activeStyle() {
return {
backgroundColor: this._radioGroup.fill,
borderColor: this._radioGroup.fill,
color: this._radioGroup.textColor
};
},
}
相關文章
- Element(React)原始碼分析系列4--Radio元件React原始碼元件
- 手寫(radio)element-ui元件UI元件
- 拜讀及分析Element原始碼-input元件篇原始碼元件
- 拜讀及分析Element原始碼-alert元件篇原始碼元件
- Element原始碼分析系列4-Radio(單選框)原始碼
- 拜讀及分析Element原始碼-form表單元件篇原始碼ORM元件
- Element-UI radio、radio-group、radio-button 單選框原始碼UI原始碼
- Flutter控制元件--Radio和RadioListTileFlutter控制元件
- element ScrollBar滾動元件原始碼深入分析元件原始碼
- 搭建自己的 vue 元件庫(二) —— Element-ui 專案分析Vue元件UI
- element 手寫季度元件元件
- 微信小程式--自定義radio元件樣式微信小程式元件
- 解讀element-ui中table元件部分原始碼與需求分析UI元件原始碼
- Element Plus的Pagination 元件用法元件
- GNU Radio 實數與複數訊號分析
- element-ui滾動條元件UI元件
- 思路:element 表格元件自適應元件
- vue專案使用element元件庫Vue元件
- Element theme-chalk 分析
- Vue3+Vite+Ts+Element Element的元件型別丟失VueVite元件型別
- Element-UI踩坑之Pagination元件UI元件
- Element-UI 框架 el-scrollbar 元件UI框架元件
- element封裝可編輯表格元件封裝元件
- 封裝Vue Element的table表格元件封裝Vue元件
- Vue + Element 自定義上傳封面元件Vue元件
- Element 指令clickoutside原始碼分析IDE原始碼
- 微服務架構元件分析,看這篇就夠了微服務架構元件
- Element外掛中Select元件的報錯元件
- Element UI 原始碼解讀之 Table 元件UI原始碼元件
- 封裝Vue Element的upload上傳元件封裝Vue元件
- 封裝Vue Element的dialog彈窗元件封裝Vue元件
- 封裝Vue Element的form表單元件封裝VueORM元件
- VUE - 區域性引用Element-UI元件VueUI元件
- Element-Ui元件(三十九)Tooltip 文字提示UI元件
- Element-Ui元件(四十)Popover 彈出框UI元件
- Element-Ui元件(四十一)Card 卡片UI元件
- element UI元件樣式重複問題UI元件
- Element修改彈窗類元件的層級元件
- 從原始碼看flutter(二):Element篇原始碼Flutter