1. <template>
  2. <label class="el-radio">
  3. <span class="el-radio__input">
  4. <span class="el-radio__inner"></span>
  5. <input type="radio" />
  6. </span>
  7. <span class="el-radio__label">
  8. <slot></slot>
  9. <template v-if="!$slots.default">{{ label }}</template>
  10. </span>
  11. </label>
  12. </template>
  • 使用 label 标签包裹,扩大鼠标点击范围,利用 span 来模拟 radio 的样式(原生不好看),span 中的 input 承载 radio 的功能,但被隐藏了

    1. <input
    2. ref="radio"
    3. class="el-radio__original"
    4. :value="label"
    5. type="radio"
    6. aria-hidden="true"
    7. v-model="model"
    8. @focus="focus = true"
    9. @blur="focus = false"
    10. @change="handleChange"
    11. :name="name"
    12. :disabled="isDisabled"
    13. tabindex="-1"
    14. />
    1. @include e(original) {
    2. opacity: 0;
    3. outline: none;
    4. position: absolute;
    5. z-index: -1;
    6. top: 0;
    7. left: 0;
    8. right: 0;
    9. bottom: 0;
    10. margin: 0;
    11. }

    将 input 透明度设为 0,脱离文档流

    1. isGroup() {
    2. let parent = this.$parent;
    3. while (parent) {
    4. if (parent.$options.componentName !== 'ElRadioGroup') {
    5. parent = parent.$parent;
    6. } else {
    7. this._radioGroup = parent;
    8. return true;
    9. }
    10. }
    11. return false;
    12. }

    通过 isGroup 判断是否处于单选组里

    1. <el-radio-group v-model="radio2">
    2. <el-radio :label="3">备选项</el-radio>
    3. <el-radio :label="6">备选项</el-radio>
    4. <el-radio :label="9">备选项</el-radio>
    5. </el-radio-group>
    1. model: {
    2. get() {
    3. return this.isGroup ? this._radioGroup.value : this.value;
    4. },
    5. set(val) {
    6. if (this.isGroup) {
    7. this.dispatch('ElRadioGroup', 'input', [val]);
    8. } else {
    9. this.$emit('input', val);
    10. }
    11. this.$refs.radio && (this.$refs.radio.checked = this.model === this.label);
    12. }
    13. }
  • 如果处于单选框组组件内时,取单选框组的 value,否则拿自己的 value

  • this.value 的值是使用 v-model 设置的(必须在 prop 中声明一个 value 的值),同时必须在 set 方法中设置 this.$emit(‘input’, val)

    参考资料

  1. Element源码分析系列4-Radio(单选框)
  2. 超详细 ElementUI 源码分析 —— Radio