Element(Vue 2 UI Toolkit)Radio 单选框组件完全指南:基础用法、分组、按钮样式与源码剖析
2026/9/18 22:39:42 网站建设 项目流程

Element(Vue 2 UI Toolkit)Radio 单选框组件完全指南:基础用法、分组、按钮样式与源码剖析

【免费下载链接】elementA Vue.js 2.0 UI Toolkit for Web项目地址: https://gitcode.com/gh_mirrors/eleme/element

本指南以examples/docs/es/radio.md文档为核心,系统讲解 Element(A Vue.js 2.0 UI Toolkit for Web)中el-radio单选框组件的基础用法、禁用状态、单选框组、按钮样式与带边框形态,并结合packages/radiopackages/radio-grouppackages/radio-button等源码与test/unit/specs/radio.spec.js测试用例,深入剖析其 v-model 双向绑定机制、组件间通信与键盘导航实现。读完本文,你将掌握 Radio 组件的全部属性、事件与实战写法,并能理解其在表单校验中的联动原理。

一、组件概览与适用场景

Radio(单选框)用于在一组备选项中进行单选。Element 文档明确给出了一条重要的使用边界:由于选项默认可见,选项数量不宜过多,若选项过多,建议改用 Select 选择器。因此在决定使用el-radio前,应先评估选项规模——少量互斥选项(如性别、状态、城市枚举)适合单选框,而长列表则更适合 Select 选择器。

组件由三个可组合的构件组成:

  • el-radio:基础单选项,支持独立使用或放入组内;
  • el-radio-group:单选框组容器,负责统一管理选中值、禁用状态、尺寸与键盘导航;
  • el-radio-button:按钮风格的单选项,必须配合el-radio-group使用。

三者通过 packages/radio/index.js、packages/radio-group/index.js、packages/radio-button/index.js 注册为全局组件(组件名分别为ElRadioElRadioGroupElRadioButton),可直接在模板中以<el-radio>形式使用。

二、基础用法:v-model 与 label 的绑定关系

要使用 Radio 组件,只需设置v-model绑定变量。选中某选项意味着变量的值等于该 Radiolabel属性的值label可以是StringNumberBoolean任意一种类型:

<template> <el-radio v-model="radio" label="1">备选项 A</el-radio> <el-radio v-model="radio" label="2">备选项 B</el-radio> </template> <script> export default { data () { return { radio: '1' }; } } </script>

初始radio: '1'与第一个选项的label="1"相等,因此页面渲染时第一个单选框处于选中状态。

源码视角:model 的计算与分发

在 packages/radio/src/radio.vue 中,选中状态通过一个model计算属性完成读写(第 93-105 行):

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); } }
  • 模板中v-model="model"绑定在原生<input type="radio">上,用户点击时原生 input 的 change 事件会触发model的 setter;
  • 独立使用时,setter 直接$emit('input', val)把新值回写给外层v-model
  • 组内使用时,则通过dispatch向上找到ElRadioGroup并触发其input事件(见 src/mixins/emitter.js 的向上冒泡实现),最终更新组级绑定值。

isGroup的判定(第 81-92 行)是沿$parent链向上查找componentName === 'ElRadioGroup'的祖先组件,因此即使el-radio嵌套在多层自定义容器中,也能正确识别所属分组。

三、禁用状态

设置disabled属性即可禁用单选框,它接受一个Booleantrue为禁用。已选中的选项在禁用后仍然保持选中态:

<template> <el-radio disabled v-model="radio" label="禁用">备选项</el-radio> <el-radio disabled v-model="radio" label="选中且禁用">备选项</el-radio> </template> <script> export default { data () { return { radio: '选中且禁用' }; } } </script>

源码中disabled为 Boolean 类型 prop(radio.vue)。其计算属性isDisabled(第 115-119 行)体现了三层禁用叠加逻辑:

isDisabled() { return this.isGroup ? this._radioGroup.disabled || this.disabled || (this.elForm || {}).disabled : this.disabled || (this.elForm || {}).disabled; }

单个选项的disabled、所属组的disabled、以及外层el-form的全局disabled任一为真,该选项即进入禁用态。这也是为什么在el-form上设置disabled可以一次性禁用整个表单内所有单选框。对应地,test/unit/specs/radio.spec.js 中的disabled用例验证了:禁用后点击不会改变绑定值,且 DOM 上会挂载is-disabled类。

四、单选框组:el-radio-group

当存在多个互斥选项时,推荐使用el-radio-group组合el-radio。在el-radio-group上绑定v-model,在每个el-radio上设置label即可,无需再给每个el-radio单独绑定变量

<template> <el-radio-group v-model="radio"> <el-radio :label="3">备选项 A</el-radio> <el-radio :label="6">备选项 B</el-radio> <el-radio :label="9">备选项 C</el-radio> </el-radio-group> </template> <script> export default { data () { return { radio: 3 }; } } </script>

注意此例中:label="3"使用了v-bind绑定数字字面量,因此选中后radio的值为数字3;若写label="3",则值为字符串'3'。这也是文档强调label可为StringNumberBoolean的实战意义所在。

组级还提供change事件响应变化,回调参数为当前选中的label值:

<el-radio-group v-model="radio" @change="handleChange"> <el-radio :label="3">备选项 A</el-radio> <el-radio :label="6">备选项 B</el-radio> </el-radio-group>

源码视角:组内通信与键盘导航

在 packages/radio/src/radio-group.vue 中:

  • 事件转发(第 55-59 行):created钩子里监听来自子选项的handleChange内部事件,再对外$emit('change', value),保证组级change只携带最新选中的值;
  • 与表单联动(第 106-110 行):watch: value在绑定值变化时向ElFormItem派发el.form.change,这是el-radio-group能无缝接入el-form校验的关键;
  • 键盘导航(第 69-104 行):handleKeydown监听组内按键,按左/上方向键回退到上一个选项(首项回绕到末项),按右/下方向键前进到下一个选项(末项回绕到首项),并同步click()focus(),实现仅靠键盘即可在组内切换——这一行为在 radio.spec.js 的keyboard event用例中被验证(模拟按 37 号左键后选中值从 6 变为 3)。

此外,组容器通过_elTag计算属性(第 45-49 行)动态决定渲染的标签名,默认渲染为<div>,并带有role="radiogroup"无障碍语义。

五、按钮样式:el-radio-button

el-radio换成el-radio-button,即可得到按钮风格的单选组合。Element 还提供了size属性控制按钮尺寸,可选值medium/small/mini

<template> <div> <el-radio-group v-model="radio1"> <el-radio-button label="New York"></el-radio-button> <el-radio-button label="Washington"></el-radio-button> <el-radio-button label="Los Angeles"></el-radio-button> <el-radio-button label="Chicago"></el-radio-button> </el-radio-group> </div> <div style="margin-top: 20px"> <el-radio-group v-model="radio2" size="medium"> <el-radio-button label="New York"></el-radio-button> <el-radio-button label="Washington"></el-radio-button> <el-radio-button label="Los Angeles"></el-radio-button> <el-radio-button label="Chicago"></el-radio-button> </el-radio-group> </div> <div style="margin-top: 20px"> <el-radio-group v-model="radio3" size="small"> <el-radio-button label="New York"></el-radio-button> <el-radio-button label="Washington" disabled></el-radio-button> <el-radio-button label="Los Angeles"></el-radio-button> <el-radio-button label="Chicago"></el-radio-button> </el-radio-group> </div> <div style="margin-top: 20px"> <el-radio-group v-model="radio4" disabled size="mini"> <el-radio-button label="New York"></el-radio-button> <el-radio-button label="Washington"></el-radio-button> <el-radio-button label="Los Angeles"></el-radio-button> <el-radio-button label="Chicago"></el-radio-button> </el-radio-group> </div> </template> <script> export default { data () { return { radio1: 'New York', radio2: 'New York', radio3: 'New York', radio4: 'New York' }; } } </script>

示例展示了四种典型组合:默认尺寸、size="medium"size="small"(含单个disabled选项)、以及整组disabled+size="mini"

源码视角:按钮激活配色如何工作

packages/radio/src/radio-button.vue 中,激活态的配色来自activeStyle计算属性(第 85-92 行):

activeStyle() { return { backgroundColor: this._radioGroup.fill || '', borderColor: this._radioGroup.fill || '', boxShadow: this._radioGroup.fill ? `-1px 0 0 0 ${this._radioGroup.fill}` : '', color: this._radioGroup.textColor || '' }; }

即激活按钮的背景色、边框色由组的fill属性决定,文本颜色由组的text-color属性决定(默认#409EFF填充、#ffffff文字),且相邻按钮间的分隔阴影也用fill色绘制。而按钮尺寸由size()计算属性(第 96-98 行)解析,优先级为:组的size> 外层el-form-item的尺寸 >$ELEMENT.size全局配置。底层样式见 packages/theme-chalk/src/radio-button.scss:首个按钮左边框与圆角特殊处理,形成连续的按钮组视觉。

六、带边框的 Radio

设置border属性可以渲染为带边框的单选框。border形态下,size属性才生效(medium/small/mini),控制整个选项框的尺寸:

<template> <div> <el-radio v-model="radio1" label="1" border>备选项1</el-radio> <el-radio v-model="radio1" label="2" border>备选项2</el-radio> </div> <div style="margin-top: 20px"> <el-radio v-model="radio2" label="1" border size="medium">备选项1</el-radio> <el-radio v-model="radio2" label="2" border size="medium">备选项2</el-radio> </div> <div style="margin-top: 20px"> <el-radio-group v-model="radio3" size="small"> <el-radio label="1" border>备选项1</el-radio> <el-radio label="2" border disabled>备选项2</el-radio> </el-radio-group> </div> <div style="margin-top: 20px"> <el-radio-group v-model="radio4" size="mini" disabled> <el-radio label="1" border>备选项1</el-radio> <el-radio label="2" border>备选项2</el-radio> </el-radio-group> </div> </template> <script> export default { data () { return { radio1: '1', radio2: '1', radio3: '1', radio4: '1' }; } } </script>

组内同样可以通过组的size统一控制每个带边框 Radio 的尺寸。源码中,el-radio的根元素类名会根据border && radioSize拼接出el-radio--medium/el-radio--small/el-radio--mini(radio.vue),样式表 packages/theme-chalk/src/radio.scss 为这些修饰类分别定义了内边距、圆角、高度与圆形指示点大小;选中时边框变为主题色$--color-primary,禁用时显示not-allowed光标。对应测试 radio.spec.js 的border用例断言根元素存在is-bordered类。

七、API 参考:属性与事件

以下三张属性表与两张事件表完整继承自 examples/docs/es/radio.md 并补充了源码级说明。

Radio Attributes

参数说明类型可选值默认值
value / v-model绑定值string / number / boolean
labelRadio 的 value(选中后绑定值变为该值)string / number / boolean
disabled是否禁用booleanfalse
border是否显示边框booleanfalse
sizeRadio 的尺寸,仅在border为真时有效stringmedium / small / mini
name原生name属性string

说明:size的计算同时兼容外层el-form-item的尺寸与$ELEMENT.size全局配置(见 radio.vue);name会透传给内部原生<input type="radio">,用于表单提交等原生场景。

Radio-button Attributes

参数说明类型可选值默认值
labelRadio 的 valuestring / number
disabled是否禁用booleanfalse
name原生name属性string

Radio-group Attributes

参数说明类型可选值默认值
value / v-model绑定值string / number / boolean
size单选框组尺寸,仅对按钮形式的 Radio 或带边框的 Radio 有效stringmedium / small / mini
disabled是否禁用整组booleanfalse
text-color按钮形式的 Radio 激活时的文本颜色string#ffffff
fill按钮形式的 Radio 激活时的填充色和边框色string#409EFF

Radio Events 与 Radio-group Events

事件名称说明回调参数
change绑定值变化(用户交互触发)时触发选中的 Radio label 值
input绑定值变化时触发(v-model 内部机制)选中的 Radio label 值

需要注意区分两个事件:

  • inputv-model的底层事件,只要绑定值变化就会触发——包括代码中直接修改绑定变量的情况;
  • change只在用户交互(点击或键盘操作)时触发,程序化地给v-model赋值不会触发change。这一行为在 radio.spec.js 的两个用例中得到验证(change event only triggers on user input),实践中有需要监听"用户真实操作"的场景(如埋点、即时保存)应使用change

八、无障碍与细节行为

从源码与测试中可以确认几个容易被忽略的细节:

  • 空格键选中el-radioel-radio-button的根<label>上都绑定了@keydown.space,禁用时不响应(radio.vue);
  • Tab 焦点管理tabIndex计算属性让"当前选中项可获得 Tab 焦点、其余项不可",且当组内没有任何默认选中项时,mounted后第一个选项会被赋予tabIndex = 0(radio-group.vue);
  • ARIA 语义:根元素带role="radio"aria-checkedaria-disabled,组容器带role="radiogroup",原生 input 使用aria-hidden="true"隐藏以避免屏幕阅读器重复朗读;
  • 原生 input 隐藏el-radio__original/el-radio-button__orig-radio均被opacity: 0z-index: -1隐藏,视觉层完全由样式化的el-radio__inner圆形指示点承担(见 radio.scss)。

九、实战建议小结

  1. 选项不超过 5~7 个时优先使用 Radio 组,更多选项改用 Select;
  2. 注意label的类型一致性label="1"(字符串)与:label="1"(数字)会得到不同类型的绑定值,初始化数据时务必与之一致;
  3. 整组禁用优先在el-radio-group上设置disabled,免去逐个配置;
  4. 需要监听用户主动选择时使用change,需要响应一切值变化时使用input/v-model
  5. 接入表单校验无需额外处理,el-radio-group已在值变化时自动向el-form-item派发el.form.change,配合 Form 表单 的校验规则即可实现选中即校验。

相关源码与测试路径:组件实现见 packages/radio/src/radio.vue、packages/radio/src/radio-group.vue、packages/radio/src/radio-button.vue;样式见 packages/theme-chalk/src/radio.scss 与 packages/theme-chalk/src/radio-button.scss;行为验证见 test/unit/specs/radio.spec.js。

【免费下载链接】elementA Vue.js 2.0 UI Toolkit for Web项目地址: https://gitcode.com/gh_mirrors/eleme/element

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询