序言
这篇的话,来分享一下Radio剩下的两个组件,radio-group、radio-button. 这两个组件的大致看了一下很多的地方和上一篇radio 90%以上是超不多的,radio和radio-button他俩最主要的区别还是样式上的不一样,还有一个原因就是,radio-button是和radio-group配合起来用的,所以这里就主要的讲一下radio-group的东西吧😁😁。
结构分析
老样子还是根据三个角度来分析,Dom、数据属性、事件
Dom
<component is=_elTag class=el-radio-group role=radiogroup @keydown=handleKeydown>
<slot></slot>
</component>
radio-group的dom结构还是非常的少的,便于理解和参考,
首先引入眼帘的就是咱们的 component 这个组件了,这个就是vue自带的组件了,还有一个就是slot。
Vue自带的标签有component,transition,transition-group,keep-alive,slot。
component标签它是Vue内置的标签,它的用途是可以动态绑定我们的组件,根据数据不同更换不同的组件,详细的可以看看官网的描述了,这里就不做很详细的描述了。
role : 这个属性在上一篇我提过 无障碍网页应用属性 大家也可以去参考看一看,这里也不多介绍了。
keydown:键盘按下事件
数据属性
const keyCode = Object.freeze({
LEFT 37,
UP 38,
RIGHT 39,
DOWN 40,
});
export default {
name ElRadioGroup,
componentName ElRadioGroup,
inject {
elFormItem {
default ,
},
},
mixins [Emitter],
props {
value {},
size String,
textColor String,
disabled Boolean,
},
computed {
_elFormItemSize() {
return (this.elFormItem {}).elFormItemSize;
},
_elTag() {
return (this.$vnode.data {}).tag div;
},
radioGroupSize() {
return this.size this._elFormItemSize (this.$ELEMENT {}).size;
},
},
属性这块的话,大部分也是之前分析过的,大家也可以参考之前的,但是这样有一个属性,大家可能平时可能用的比较少
Object.freeze: (冻结一个对象)一个被冻结的对象再也不能被修改;冻结了一个对象则不能向这个对象添加新的属性,不能删除已有属性,不能修改该对象已有属性的可枚举性、可配置性、可写性,以及不能修改已有属性的值。此外,冻结一个对象后该对象的原型也不能被修改。freeze()
返回和传入的参数相同的对象。
computed
_elFormItemSize:用来判断当前from的
_elTag: 这个就是用来区分 按钮的组件和普通的组件了
radioGroupSize:Group的大小
事件
created() {
this.$on(handleChange, (value) = {
this.$emit(change, value);
});
},
mounted() {
当radioGroup没有默认选项时,第一个可以选中Tab导航
const radios = this.$el.querySelectorAll([type=radio]);
const firstLabel = this.$el.querySelectorAll([role=radio])[0];
if (![].some.call(radios, (radio) = radio.checked) && firstLabel) {
firstLabel.tabIndex = 0;
}
},
methods {
左右上下按键 可以在radio组内切换不同选项
handleKeydown(e) {
const target = e.target;
当前按下元素的事件对象
const className = target.nodeName === INPUT [type=radio] [role=radio];
判断当前的元素是否是对应的INPUT,然后再来选择对应的input或者label
const radios = this.$el.querySelectorAll(className);
获取所有的className
const length = radios.length;
获取对应input或者label的数量
const index = [].indexOf.call(radios, target);
在this.$el.querySelectorAll的集合中查找evevt.target当前的下标
可以理解为radios的对象继承了空数组的indexOf方法,按下时找到radios出现的位置
const roleRadios = this.$el.querySelectorAll([role=radio]);
获取所有的 label标签
switch (e.keyCode) {
左
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;
default
break;
}
},
},
created : 主要是来监听子组件的handleChange,并且把这个事件抛出来。
handleKeydown:这个方法主要的作用就是左右上下按键 可以在radio组内切换不同选项,详细的看上方注释
小知识点(续)
在关于 Radio-group 这篇文章中有一个疑问,之前没有注意到 这里的话解释一下!
在handleKeydown事件中有这么一行代码
源码
const index = [].indexOf.call(radios, target);
完整的写法是
const index = [].indexOf.call(this.$el.querySelectorAll('[type=radio]'), e.target);
问题1: 这里为什么要用到call方法
首先通过 querySelectorAll 等方法获取到指定元素列表,这个元素列表被称为类数组
类数组定义
1)拥有length属性,其它属性(索引)为非负整数(对象中的索引会被当做字符串来处理);
2)类数组不具有数组所具有的方法;
3)类数组是一个普通对象,他的原型是Object,而真实的数组是Array类型
4)常见的类数组有: 函数的参数 arguments, DOM 对象列表(比如通过 document.querySelectorAll 得到的列表)
类数组转数组的方法 (这只是一部分)
1)[].slice.call([类数组]);
2)[...[类数组]];
3)Array.from([类数组]);
问题2: 这里为什么要用IndexOf.call() 他的作用是什么
其实这里有一个场景,一个父级下有多个子级,我们要给按下某个子级的时候做对应的操作。
1)循环遍历 给每个子级添加对应的方法
2)写很多判断 进行区分
3)利用事件委托的形式来区分子级
招聘广告
言重式招聘 寻人!!!寻志同道合之人、寻竭忠尽智之人、寻深思远虑之人、寻勤恳至诚之人
浙江大华技术股份有限公司-软研-智慧城市产品研发部招聘高级前端!!!!!
欢迎大家来聊,有意向可发送简历到chen_zhen@dahuatech.com
树大招风风撼树,人为高名名丧人 ——————无奖竞猜