element-ui源码阅读笔记(radio篇)

本文深入剖析 Element UI 的 Radio 组件实现原理,包括样式绑定、无障碍属性的应用、Tab 键导航支持及值的双向绑定过程。此外还介绍了单选按钮组如何处理键盘导航。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

按照element-ui文档的顺序,button后的第二个组件就是radio了。

第一眼看到的就是class的绑定不一般,罒ω罒

:class="[
  border && radioSize ? 'el-radio--' + radioSize : '',
  { 'is-disabled': isDisabled },
  { 'is-focus': focus },
  { 'is-bordered': border },
  { 'is-checked': model === label }
]"
复制代码

对着vue文档的Class绑定一节看了半天,发现数组绑定是有对象绑定不能替代的部分,即

  border && radioSize ? 'el-radio--' + radioSize : '',
复制代码

className可以变化,所以class的数组绑定方式是万金油的写法(虽然有些繁琐)。(className用了is-*,讲究)

第二眼就看到了aria-*,这为辅助设备提供相应的标识(这也是为什么盲人也可以使用饿了么点外卖,点赞)

:aria-checked="model === label"
:aria-disabled="isDisabled" 
复制代码

第三眼(真是每行都是精华呀)看到了:tabindex="tabIndex",这是规定页面元素的 tab 键控制次序,element-ui的表单元素支持按tab键选中,按enter或者space键点击的。

第四眼,radio的层级有很多,还不清楚是为什么,最后的html是

<span class="el-radio__label" @keydown.stop>
  <slot></slot>
  <template v-if="!$slots.default">{{label}}</template>
</span>
复制代码

这里对<el-radio></el-radio>的标签中是否添加文字做了判断,如果添加文字,会放在$slots.default中。

最后统一讲一下值传递的过程:

当v-model用在组件上时,是这样的

<input v-model="searchText">
复制代码

等于

<custom-input
    v-bind:value="searchText"
    v-on:input="searchText = $event"
></custom-input>
复制代码

所以需要从props: { value: {}}里取得在组件上用v-model绑定的值。

然后在计算方法里转换为绑定在真实radio上的值

  <input
    class="el-radio__original"
    :value="label"
    type="radio"
    aria-hidden="true"
    v-model="model"
复制代码

model即为下面计算方法中的model,同时起到了双向绑定的作用。值得注意的是,此处的set只提交了input改变,没提交change改变,从应用的角度来说,就是js修改而不是点击修改的,不会提交change(自己代码修改带来的变化自己处理,element只是更新数据了)

  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);
      }
    }
  },
复制代码

change方法是在nextTick,就是更新dom之后才提交更新,学到了,记笔记

    this.$nextTick(() => {
      this.$emit('change', this.model);
      this.isGroup && this.dispatch('ElRadioGroup', 'handleChange', this.model);
    });
复制代码

单选按钮组就添加了监控上下左右按键的监听,做了边界判断

      case keyCode.LEFT:
      case keyCode.UP:
        e.stopPropagation();
        e.preventDefault();
        if (index === 0) {
          roleRadios[length - 1].click();
          roleRadios[length - 1].focus();
        } else {
          roleRadios[index - 1].click();
          roleRadios[index - 1].focus();
        }
        break;
      case keyCode.RIGHT:
      case keyCode.DOWN:
        if (index === (length - 1)) {
          e.stopPropagation();
          e.preventDefault();
          roleRadios[0].click();
          roleRadios[0].focus();
        } else {
          roleRadios[index + 1].click();
          roleRadios[index + 1].focus();
        }
        break;
复制代码

转载于:https://juejin.im/post/5b8e7f2fe51d451a447a9773

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值