<template>
<label class="el-radio">
<span class="el-radio__input">
<span class="el-radio__inner"></span>
<input type="radio" />
</span>
<span class="el-radio__label">
<slot></slot>
<template v-if="!$slots.default">{{ label }}</template>
</span>
</label>
</template>
使用 label 标签包裹,扩大鼠标点击范围,利用 span 来模拟 radio 的样式(原生不好看),span 中的 input 承载 radio 的功能,但被隐藏了
<input
ref="radio"
class="el-radio__original"
:value="label"
type="radio"
aria-hidden="true"
v-model="model"
@focus="focus = true"
@blur="focus = false"
@change="handleChange"
:name="name"
:disabled="isDisabled"
tabindex="-1"
/>
@include e(original) {
opacity: 0;
outline: none;
position: absolute;
z-index: -1;
top: 0;
left: 0;
right: 0;
bottom: 0;
margin: 0;
}
将 input 透明度设为 0,脱离文档流
isGroup() {
let parent = this.$parent;
while (parent) {
if (parent.$options.componentName !== 'ElRadioGroup') {
parent = parent.$parent;
} else {
this._radioGroup = parent;
return true;
}
}
return false;
}
通过 isGroup 判断是否处于单选组里
<el-radio-group v-model="radio2">
<el-radio :label="3">备选项</el-radio>
<el-radio :label="6">备选项</el-radio>
<el-radio :label="9">备选项</el-radio>
</el-radio-group>
model: {
get() {
return this.isGroup ? this._radioGroup.value : this.value;
},
set(val) {
if (this.isGroup) {
this.dispatch('ElRadioGroup', 'input', [val]);
} else {
this.$emit('input', val);
}
this.$refs.radio && (this.$refs.radio.checked = this.model === this.label);
}
}
如果处于单选框组组件内时,取单选框组的 value,否则拿自己的 value
- this.value 的值是使用 v-model 设置的(必须在 prop 中声明一个 value 的值),同时必须在 set 方法中设置 this.$emit(‘input’, val)
参考资料