first
This commit is contained in:
8
packages/radio/index.js
Normal file
8
packages/radio/index.js
Normal file
@@ -0,0 +1,8 @@
|
||||
import Radio from './src/radio';
|
||||
|
||||
/* istanbul ignore next */
|
||||
Radio.install = function(Vue) {
|
||||
Vue.component(Radio.name, Radio);
|
||||
};
|
||||
|
||||
export default Radio;
|
114
packages/radio/src/radio-button.vue
Normal file
114
packages/radio/src/radio-button.vue
Normal file
@@ -0,0 +1,114 @@
|
||||
<template>
|
||||
<label
|
||||
class="el-radio-button"
|
||||
:class="[
|
||||
size ? 'el-radio-button--' + size : '',
|
||||
{ 'is-active': value === label },
|
||||
{ 'is-disabled': isDisabled },
|
||||
{ 'is-focus': focus }
|
||||
]"
|
||||
role="radio"
|
||||
:aria-checked="value === label"
|
||||
:aria-disabled="isDisabled"
|
||||
:tabindex="tabIndex"
|
||||
@keydown.space.stop.prevent="value = isDisabled ? value : label"
|
||||
>
|
||||
<input
|
||||
class="el-radio-button__orig-radio"
|
||||
:value="label"
|
||||
type="radio"
|
||||
v-model="value"
|
||||
:name="name"
|
||||
@change="handleChange"
|
||||
:disabled="isDisabled"
|
||||
tabindex="-1"
|
||||
@focus="focus = true"
|
||||
@blur="focus = false"
|
||||
>
|
||||
<span
|
||||
class="el-radio-button__inner"
|
||||
:style="value === label ? activeStyle : null"
|
||||
@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: 'ElRadioButton',
|
||||
|
||||
mixins: [Emitter],
|
||||
|
||||
inject: {
|
||||
elForm: {
|
||||
default: ''
|
||||
},
|
||||
elFormItem: {
|
||||
default: ''
|
||||
}
|
||||
},
|
||||
|
||||
props: {
|
||||
label: {},
|
||||
disabled: Boolean,
|
||||
name: String
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
focus: false
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
value: {
|
||||
get() {
|
||||
return this._radioGroup.value;
|
||||
},
|
||||
set(value) {
|
||||
this._radioGroup.$emit('input', value);
|
||||
}
|
||||
},
|
||||
_radioGroup() {
|
||||
let parent = this.$parent;
|
||||
while (parent) {
|
||||
if (parent.$options.componentName !== 'ElRadioGroup') {
|
||||
parent = parent.$parent;
|
||||
} else {
|
||||
return parent;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
},
|
||||
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 || ''
|
||||
};
|
||||
},
|
||||
_elFormItemSize() {
|
||||
return (this.elFormItem || {}).elFormItemSize;
|
||||
},
|
||||
size() {
|
||||
return this._radioGroup.radioGroupSize || this._elFormItemSize || (this.$ELEMENT || {}).size;
|
||||
},
|
||||
isDisabled() {
|
||||
return this.disabled || this._radioGroup.disabled || (this.elForm || {}).disabled;
|
||||
},
|
||||
tabIndex() {
|
||||
return (this.isDisabled || (this._radioGroup && this.value !== this.label)) ? -1 : 0;
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
handleChange() {
|
||||
this.$nextTick(() => {
|
||||
this.dispatch('ElRadioGroup', 'handleChange', this.value);
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
111
packages/radio/src/radio-group.vue
Normal file
111
packages/radio/src/radio-group.vue
Normal file
@@ -0,0 +1,111 @@
|
||||
<template>
|
||||
<component
|
||||
:is="_elTag"
|
||||
class="el-radio-group"
|
||||
role="radiogroup"
|
||||
@keydown="handleKeydown"
|
||||
>
|
||||
<slot></slot>
|
||||
</component>
|
||||
</template>
|
||||
<script>
|
||||
import Emitter from 'element-ui/src/mixins/emitter';
|
||||
|
||||
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,
|
||||
fill: 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;
|
||||
}
|
||||
},
|
||||
|
||||
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: {
|
||||
handleKeydown(e) { // 左右上下按键 可以在radio组内切换不同选项
|
||||
const target = e.target;
|
||||
const className = target.nodeName === 'INPUT' ? '[type=radio]' : '[role=radio]';
|
||||
const radios = this.$el.querySelectorAll(className);
|
||||
const length = radios.length;
|
||||
const index = [].indexOf.call(radios, target);
|
||||
const roleRadios = this.$el.querySelectorAll('[role=radio]');
|
||||
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;
|
||||
}
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
value(value) {
|
||||
this.dispatch('ElFormItem', 'el.form.change', [this.value]);
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
133
packages/radio/src/radio.vue
Normal file
133
packages/radio/src/radio.vue
Normal file
@@ -0,0 +1,133 @@
|
||||
<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: {
|
||||
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>
|
Reference in New Issue
Block a user