2020,05,20/21,没有甜蜜的约会,也是刻苦努力学习的一天呢~~~·
今天分析的是el-radio 先看看效果吧
先看elment代码
<template>
<label
class="el-radio"
:class="[
border && radioSize ? 'el-radio--' + 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"
>
<span class="el-radio__input"
:class="{
'is-disabled': isDisabled,
'is-checked': model === label
}"
>
<span class="el-radio__inner"></span>
<input
ref="radio"
class="el-radio__original"
:value="label"
type="radio"
aria-hidden="true"
v-model="model"
@focus="focus = true"
@blur="focus = false"
@change="handleChange"
:name="name"
:disabled="isDisabled"
tabindex="-1"
>
</span>
<span class="el-radio__label" @keydown.stop>
<slot></slot>
<template v-if="!$slots.default">{{label}}</template>
</span>
</label>
</template>
<script>
import Emitter from 'element-ui/src/mixins/emitter';
export default {
name: 'ElRadio',
mixins: [Emitter],
inject: {
elForm: {
default: ''
},
elFormItem: {
default: ''
}
},
componentName: 'ElRadio',
props: {
value: {},
label: {},
disabled: Boolean,
name: String,
border: Boolean,
size: String
},
data() {
return {
focus: false
};
},
computed: {
//判断自己是否在el-radio-group里面
isGroup() {
let parent = this.$parent;
while (parent) {
if (parent.$options.componentName !== 'ElRadioGroup') {
parent = parent.$parent;
} else {
this._radioGroup = parent;
return true;
}
}
return false;
},
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);
}
},
_elFormItemSize() {
return (this.elFormItem || {}).elFormItemSize;
},
radioSize() {
const temRadioSize = this.size || this._elFormItemSize || (this.$ELEMENT || {}).size;
return this.isGroup
? this._radioGroup.radioGroupSize || temRadioSize
: temRadioSize;
},
isDisabled() {
return this.isGroup
? this._radioGroup.disabled || this.disabled || (this.elForm || {}).disabled
: this.disabled || (this.elForm || {}).disabled;
},
tabIndex() {
return (this.isDisabled || (this.isGroup && this.model !== this.label)) ? -1 : 0;
}
},
methods: {
handleChange() {
this.$nextTick(() => {
this.$emit('change', this.model);
this.isGroup && this.dispatch('ElRadioGroup', 'handleChange', this.model);
});
}
}
};
</script>
label
先看看官方的说法
写过按钮组件朋友都知道,原生的样式很丑,基本不能满足UI小姐姐们画的漂亮的按钮样式,需要自己重写样式。 很明显element组件也是重写的样式, 我们可以看到整个组件外层是一个label标签,作用就是扩大点击范围。 label里面第一个sapn就是模拟那个选中的圈圈,input被隐藏起来,显示的是span的样式,但是实际点击选中的还是input label里面第二个span表示文字部分,默认渲染文本,如果没有文本,就渲染label的值。
再看看label的属性
<label
class="el-radio" //命名class
:class="[
//定义边框
border && radioSize ? 'el-radio--' + 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"
>
</label>
class里面还是有很多计算属性的,让我们来看看~
- 第一个:
'is-disabled': isDisabled对应的js代码部分
isDisabled() {
return this.isGroup
? this._radioGroup.disabled || this.disabled || (this.elForm || {}).disabled
: this.disabled || (this.elForm || {}).disabled;
},
isGroup判断自己是否在el-radio-group里面, 看看isGroup的代码
//是一个while循环,这里的$parent是寻找父级实例,$options 实例的初始化选项,
isGroup() {
let parent = this.$parent;
while (parent) {
if (parent.$options.componentName !== 'ElRadioGroup') {
parent = parent.$parent;
} else {
this._radioGroup = parent;
return true;
}
}
return false;
},
那么理解这个就可以知道isDisabled的意思了,如果自己在单选框组件里面,那么整个框组件都被禁用,如果不在单选框组件里面的话,就只禁用自己
-
第二个
'is-focus': focus代表label标签是否获得focus类,focus是在input标签上去处理的。input是否获得焦点。 -
第三个
'is-bordered': border是否有边框,看用户传ture还是false来判断是否渲染边框 -
第四个
'is-checked': model === label是否选中,此处model也是一个计算属性 上代码
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哈,get ,set,这里也确实是和v-model很相似,get先判断自己是不是在group里面,如果在就返回单选框组的值,如果不是就返回自己的值.
下面的get也是,但是这个dispatch在这里就有点耐人寻味哈,我们晓得vuex里面dispatch就是事件通知的意思哈。 在这里可不是这个意思哈,写法都不一样。 我一开始也不知道是啥,看到了这个页面有引入mixins的内容。点进去看了一下是element封装的自己的方法,就是根据组件名,触发相应的方法,传入数值。 不断地取到自己的父组件,判断是否是目标组件,如果不是继续去其父组件判断,如果是则在父组件上调用$emit触发事件,
dispatch(componentName, eventName, params) {
var parent = this.$parent || this.$root;
var name = parent.$options.componentName;
while (parent && (!name || name !== componentName)) {
parent = parent.$parent;
if (parent) {
name = parent.$options.componentName;
}
}
if (parent) {
parent.$emit.apply(parent, [eventName].concat(params));
}
},
$nextTick()
在这里,我也不晓得有啥用~~~~。。。 继续调查调查