radio

  1. label放在最外层的作用是扩大鼠标点击范围,无论是点击在文字还是input上都能够触发响

    <label class="el-radio"><!-- 单选框 --><span class="el-radio__input"></span><!-- 文字部分 --><span class="el-radio__label"></span>
    </label>
    
    <template><labelclass="el-radio":class="{[`el-radio--${radioSize || ''}`]: border && radioSize,'is-disabled': isDisabled,'is-focus': focus,'is-bordered': border,'is-checked': model === label}"role="radio":aria-checked="model === label":aria-disabled="isDisabled":tabindex="tabIndex"@keydown.space.stop.prevent="model = isDisabled ? model : label"><!-- :tabindex="tabIndex"@keydown.space.stop.prevent="model = isDisabled ? model : label"这个功能是为了用tab切换不同选项时,按空格可以快速选择目标项 --><!-- 模拟圆形按钮 --><spanclass="el-radio__input":class="{'is-disabled': isDisabled,'is-checked': model === label}"><!-- 圆形样式 --><span class="el-radio__inner"></span><!-- 真正的按钮 --><!-- el-radio__original ⚠️注意这个样式 --><inputref="radioRef"v-model="model"class="el-radio__original":value="label"type="radio"aria-hidden="true":name="name":disabled="isDisabled"tabindex="-1"@focus="focus = true"@blur="focus = false"@change="handleChange"></span><!-- 文字部分 --><!-- keydown.stop 阻止事件继续冒泡 --><span class="el-radio__label" @keydown.stop><slot>{{ label }}</slot></span></label>
    </template>
    
  2. el-radio__original

    .el-radio__original {opacity: 0;outline: none;position: absolute;z-index: -1;top: 0;left: 0;right: 0;bottom: 0;margin: 0;
    }
    

    真正的input透明度为0,且是绝对定位脱离文档流,因此我们看不到,但是是有大小的,注意不是display:none或者visibility:hidden,如果是none或者hidden的话则无法触发鼠标点击了,只有opacity:0才能达到目的,这是个需要注意的地方

  3. disabled

    样式上的disabled绑定在label 上,功能上的disabled绑定在input

    const isDisabled = computed(() => {return isGroup.value? radioGroup.disabled || props.disabled || elForm.disabled: props.disabled || elForm.disabled})
    

    isGroupelForm的取值都是通过inject注入

    const radioGroup = inject(radioGroupKey, {} as RadioGroupContext)
    const isGroup = computed(() => radioGroup?.name === 'ElRadioGroup')
    
  4. role="radio"
    :aria-checked="model === label"
    :aria-disabled="isDisabled"
    

    rolerole的作用是描述一个非标准的tag的实际作用。比如用div做button,那么设置div 的 role=“button”,辅助工具就可以认出这实际上是个button。

    aria-*的作用就是描述这个tag在可视化的情境中的具体信息

    此tag 是一个radiocheckeddisabled 的属性分别是什么

  5. :tabindex="tabIndex"
    @keydown.space.stop.prevent="model = isDisabled ? model : label"
    

    tabindex规定了按下tab键该元素获取焦点的顺序,同样是个计算属性

    const tabIndex = computed(() => {return (isDisabled.value || (isGroup.value && model.value !== props.label)) ? -1 : 0})
    
    • tabindex=负值 (通常是tabindex=“-1”),表示元素是可聚焦的,但是不能通过键盘导航来访问到该元素,用JS做页面小组件内部键盘导航的时候非常有用。

    • tabindex="0" ,表示元素是可聚焦的,并且可以通过键盘导航来聚焦到该元素,它的相对顺序是当前处于的DOM结构来决定的。

    • tabindex=正值,表示元素是可聚焦的,并且可以通过键盘导航来访问到该元素;它的相对顺序按照tabindex 的数值递增而滞后获焦。如果多个元素拥有相同的 tabindex,它们的相对顺序按照他们在当前DOM中的先后顺序决定。

    @keydown.space.stop.prevent="model = isDisabled ? model : label"

    这个功能是为了用tab切换不同选项时,按空格可以快速选择目标项 (先通过tab 切换聚焦,在通过space选择当前聚焦的项目)

  6. focus

    //radio.vue
    const focus = ref(false)//控制focus样式 click时,不显示focus样式<label  :class="{'is-focus': focus,...}"><input @focus="focus = true"@blur="focus = false">
    
    .el-radio:focus:not(.is-focus):not(:active):not(.is-disabled) .el-radio__inner {box-shadow: 0 0 2px 2px #409eff;
    }
    

    tab切换,会出现foucs样式,但不会触发@focus事件因为label上添加的:tabindex="tabIndex",而input的:tabindex="-1",所以虽然有样式,但不会触发input的@focus事件

    click时,同时也会出现focus样式,触发@focus事件,此时不想有focus的样式,所以添加一个is-focus

  7. model

    const model = computed<string | number | boolean>({get() {return isGroup.value ? radioGroup.modelValue : props.modelValue},set(val) {if (isGroup.value) {radioGroup.changeEvent(val)//injdect radioGroup 修改radioGroup的v-model值} else {ctx.emit(UPDATE_MODEL_EVENT, val)//update:modelValue 修改radio的v-model值}radioRef.value.checked = props.modelValue === props.label//dom 对象上的 checked 属性},})
    

    Model通过computed计算而来,

    get : 获取值

    Set: 修改值

  8. nextTick

    function handleChange() {nextTick(() => {ctx.emit('change', model.value)})
    }
    

    此处为什么使用nextTick?感觉不使用也没问题❓

    我认为 radio-group 中已确保了执行循序,所以radio的change 无论是单独使用还是在group内总是最后执行的,所以我认为使不使用nextTick都可以。希望有人帮忙解惑,谢谢

radio-group

  1. nextTick

    const changeEvent = value => {ctx.emit(UPDATE_MODEL_EVENT, value)//update:modelValuenextTick(() => {ctx.emit('change', value)})}
    

    此处nextTick作用,保证执行顺序。 先 ctx.emit(UPDATE_MODEL_EVENT, value),后 ctx.emit(‘change’, value),保证v-model变化会优先于change执行。
    如果没有 nextTick,执行顺序相反,
    因为ctx.emit(UPDATE_MODEL_EVENT, value),更新值的变化,会导致页面更新,所以会在下次页面更新时执行。而chang事件会在当前执行

  2. 选中切换

    // '@element-plus/utils/aria'
    export const EVENT_CODE = {tab: 'Tab',enter: 'Enter',space: 'Space',left: 'ArrowLeft', // 37up: 'ArrowUp', // 38right: 'ArrowRight', // 39down: 'ArrowDown', // 40esc: 'Escape',delete: 'Delete',backspace: 'Backspace',
    }
    //radio-group.vueconst handleKeydown = e => { // 左右上下按键 可以在radio组内切换不同选项const target = e.targetconst className = target.nodeName === 'INPUT' ? '[type=radio]' : '[role=radio]'//radio||labelconst radios = radioGroup.value.querySelectorAll(className)const length = radios.lengthconst index = Array.from(radios).indexOf(target)const roleRadios = radioGroup.value.querySelectorAll('[role=radio]')let nextIndex = nullswitch (e.code) {case EVENT_CODE.left:case EVENT_CODE.up://⬅️⬆️ 选中前一个e.stopPropagation()//阻止冒泡e.preventDefault()//阻止默认行为//如果当前选中的是第一个,则下一个选中的是最后一个,否则是前一个nextIndex = index === 0 ? length - 1 : index - 1breakcase EVENT_CODE.right:case EVENT_CODE.down://➡️⬇️ 选中后一个e.stopPropagation()e.preventDefault()//如果当前选中的是最后一个,则下一个选中的是第一个,否则是后一个nextIndex = (index === (length - 1)) ? 0 : index + 1breakdefault:break}if (nextIndex === null) returnroleRadios[nextIndex].click()roleRadios[nextIndex].focus()}
    

radio-button

  1. label放在最外层的作用是扩大鼠标点击范围,无论是点击在文字还是input上都能够触发响

  2. 同上

    .el-radio-button__orig-radio {opacity: 0;outline: none;position: absolute;z-index: -1;
    }
    

element-plus 源码学习——radio相关推荐

  1. vue实例没有挂载到html上,vue 源码学习 - 实例挂载

    前言 在学习vue源码之前需要先了解源码目录设计(了解各个模块的功能)丶Flow语法. src ├── compiler # 把模板解析成 ast 语法树,ast 语法树优化,代码生成等功能. ├── ...

  2. ConcurrentHashMap源码学习

    ConcurrentHashMap源码学习 自从学习了AQS之后,想着重新读一下ConcurrentHashMap的源码来加深下理解,所以有了这篇文章,针对ConcurrentHashMap常用的方法 ...

  3. vue源码学习--vue源码学习入门

    本文为开始学习vue源码的思路整理.在拿到vue项目源码的之后看到那些项目中的文件夹,会很困惑,不知道每个文件夹内的世界,怎么变换,怎样的魔力,最后产生了vue框架.学习源码也无从学起.我解决了这些困 ...

  4. JAVA小项目实例源码—学习娱乐小助手

    代码地址如下: http://www.demodashi.com/demo/11456.html 一.程序实现 项目目录: MyJFrame:实现项目界面样式: AppProcess:实现调用api或 ...

  5. RecyclerView源码学习笔记(一)构造函数和setLayoutManager方法

    前言 RecyclerView已经出来很久,现在几乎应该都会用RecyclerView代替Listview,虽然我觉得大多数人应该还是不太清楚这两者之前的区别的,或者说RecyclerView相对于L ...

  6. JDK11源码学习05 | HashMap类

    JDK11源码学习05 | HashMap类 JDK11源码学习01 | Map接口 JDK11源码学习02 | AbstractMap抽象类 JDK11源码学习03 | Serializable接口 ...

  7. 博通Broadcom SDK源码学习与开发12终结篇——TR069网管协议

    声明:原创作品,严禁用于商业目的. 本系列文章将全面剖析以Bcm33xxx芯片开发Cablemodem产品的SDK源码为例,从编译系统到各个功能模块进行分析与探讨. 文章目录 0.写在前篇 1. TR ...

  8. Opencascade源码学习之模型算法_TKO模块文件介绍

    Opencascade源码学习之模型数据_TKO模块文件介绍 1.TKO 1.BOPAlgo 2.BOPDS 3.BOPTools 4.BRepAlgoAPI 5.IntTools 1.TKO 1.B ...

  9. 【博学谷学习记录】超强总结,用心分享 | 架构师 Mybatis源码学习总结

    Mybatis源码学习 文章目录 Mybatis源码学习 一.Mybatis架构设计 二.源码剖析 1.如何解析的全局配置文件 解析配置文件源码流程 2.如何解析的映射配置文件 Select inse ...

最新文章

  1. Python必备收藏!Pycharm 常用快捷键方式!让鼠标离手操作
  2. OpenCV纠正文本中的偏斜(附完整代码)
  3. 2019年总结 | 31岁,不过是另一个开始
  4. 使用uiautomator2进行webview页面的测试
  5. 工作两年多的一个菜鸟感想
  6. Codewars-Javascript训练手册:Date 对象
  7. web前端之框架(frameset)
  8. python基础知识-Python基础知识点总结
  9. CPDA数据分析师证书含金量高吗?
  10. 从嵌入式系统到无线模组 周立功单片机欲站在物联网的风口
  11. 注销公司是否需要办理注销呼叫中心许可证?
  12. 鼠标滑过,二级菜单显示
  13. pic16f1829 c语言,PIC16F1829 串口初始化程序及应用
  14. jeecg-boot自动生成代码_PSIM 仿真:如何使用 PSIM12 自动生成代码
  15. C语言中void具体有什么作用
  16. 最新MSNMessenger机器人列表(转)
  17. 蓝牙5.1之Direction Finding
  18. 达芬奇的这本“禁书”,竟让全世界顶礼膜拜了 500 年!
  19. MATLAB时间序列2(ARIMA,季节性序列及其预报)------2019/8/14
  20. 干货 | 什么是进销存,企业应该如何选择进销存软件?

热门文章

  1. 如何查找重复文件并快速删除,电脑查重复文件的方法
  2. 公里与英里的换算c语言函数_80迈=80迈=80公里?过年了许多开车回家的老司机都未必清楚!...
  3. 三方协议接收节点不存在_三方协议扣款常见问题及解决方法
  4. java,mysql,oracle出现科学记数法问题
  5. ppt中如何合并流程图_PPT流程图文件的合并
  6. 杨凌职业技术学院计算机专业宿舍,杨凌职业技术学院宿舍怎么样
  7. linux文件搜索关键字并显示前后10行
  8. 开机自检,BIOS运行原理
  9. python中怎样向字典中添加值_python中向一个字典中加值
  10. Excel 2010 VBA 入门 140 在功能区添加按钮并运行VBA程序