mirror of
https://gitee.com/ant-design-vue/ant-design-vue.git
synced 2024-12-02 03:58:05 +08:00
radio
This commit is contained in:
parent
c7fecd1c6e
commit
3983e6d5b8
@ -6,7 +6,7 @@
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import Checkbox from './checkbox.vue'
|
||||
import Checkbox from './Checkbox.vue'
|
||||
export default {
|
||||
name: 'CheckboxGroup',
|
||||
props: {
|
||||
@ -23,10 +23,6 @@ export default {
|
||||
type: Array,
|
||||
},
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
}
|
||||
},
|
||||
model: {
|
||||
prop: 'value',
|
||||
},
|
@ -59,9 +59,6 @@ export default {
|
||||
},
|
||||
methods: {
|
||||
handleChange (event) {
|
||||
if (this.disabled) {
|
||||
return false
|
||||
}
|
||||
const checked = event.target.checked
|
||||
this.$emit('input', checked)
|
||||
const { name, value } = this
|
||||
|
@ -1,5 +1,5 @@
|
||||
import Checkbox from './checkbox.vue'
|
||||
import CheckboxGroup from './checkbox-group.vue'
|
||||
import Checkbox from './Checkbox.vue'
|
||||
import CheckboxGroup from './Group.vue'
|
||||
|
||||
Checkbox.Group = CheckboxGroup
|
||||
export default Checkbox
|
||||
|
@ -1,9 +1,12 @@
|
||||
import './button/style'
|
||||
import './checkbox/style'
|
||||
import './icon/style'
|
||||
import './radio/style'
|
||||
|
||||
export { default as Button } from './button'
|
||||
|
||||
export { default as Checkbox } from './checkbox'
|
||||
|
||||
export { default as Icon } from './icon'
|
||||
|
||||
export { default as Radio } from './radio'
|
||||
|
81
components/radio/Group.vue
Normal file
81
components/radio/Group.vue
Normal file
@ -0,0 +1,81 @@
|
||||
<template>
|
||||
<div :class="`${prefixCls}`">
|
||||
<Radio v-for="item in options" :key="item.value" :checked="item.value === value"
|
||||
:value="item.value" :disabled="item.disabled" @change="handleChange">{{item.label}}</Radio>
|
||||
<slot v-if="options.length === 0"></slot>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import Radio from './Radio.vue'
|
||||
export default {
|
||||
name: 'RadioGroup',
|
||||
props: {
|
||||
prefixCls: {
|
||||
default: 'ant-radio-group',
|
||||
type: String,
|
||||
},
|
||||
value: [String, Number],
|
||||
size: {
|
||||
default: 'default',
|
||||
validator (value) {
|
||||
return ['large', 'default', 'small'].includes(value)
|
||||
},
|
||||
},
|
||||
options: {
|
||||
default: () => [],
|
||||
type: Array,
|
||||
},
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
curValue: this.value,
|
||||
}
|
||||
},
|
||||
model: {
|
||||
prop: 'value',
|
||||
},
|
||||
computed: {
|
||||
|
||||
},
|
||||
created () {
|
||||
this.setChildRadio(this.$slots.default)
|
||||
},
|
||||
methods: {
|
||||
handleChange (event) {
|
||||
if (this.disabled) {
|
||||
return false
|
||||
}
|
||||
const target = event.target
|
||||
const { value } = target
|
||||
this.$emit('input', value)
|
||||
this.$emit('change', value)
|
||||
},
|
||||
setChildRadio (children = []) {
|
||||
const { options, $slots, value } = this
|
||||
if (options.length === 0 && $slots.default) {
|
||||
children.forEach(({ componentOptions = {}, children: newChildren }) => {
|
||||
const { tag, propsData } = componentOptions
|
||||
if (tag === 'Radio') {
|
||||
propsData.isGroup = true
|
||||
propsData.onGroupChange = this.handleChange
|
||||
propsData.checked = propsData.value === value
|
||||
} else {
|
||||
this.setChildRadio(newChildren)
|
||||
}
|
||||
}, this)
|
||||
}
|
||||
},
|
||||
},
|
||||
beforeUpdate () {
|
||||
this.setChildRadio(this.$slots.default)
|
||||
},
|
||||
watch: {
|
||||
value (val) {
|
||||
this.setChildRadio(this.$slots.default)
|
||||
},
|
||||
},
|
||||
components: {
|
||||
Radio,
|
||||
},
|
||||
}
|
||||
</script>
|
79
components/radio/Radio.vue
Normal file
79
components/radio/Radio.vue
Normal file
@ -0,0 +1,79 @@
|
||||
<template>
|
||||
<label :class="classes">
|
||||
<span :class="checkboxClass">
|
||||
<input :name="name" type="radio" :disabled="disabled"
|
||||
:class="`${prefixCls}-input`" :checked="!!checked"
|
||||
@change="handleChange"
|
||||
/>
|
||||
<span :class="`${prefixCls}-inner`" />
|
||||
</span>
|
||||
<span v-if="hasDefaultSlot">
|
||||
<slot></slot>
|
||||
</span>
|
||||
</label>
|
||||
</template>
|
||||
<script>
|
||||
export default {
|
||||
name: 'Radio',
|
||||
props: {
|
||||
prefixCls: {
|
||||
default: 'ant-radio',
|
||||
type: String,
|
||||
},
|
||||
checked: Boolean,
|
||||
disabled: Boolean,
|
||||
isGroup: Boolean,
|
||||
value: [String, Number, Boolean],
|
||||
name: String,
|
||||
indeterminate: Boolean,
|
||||
onGroupChange: Function,
|
||||
},
|
||||
model: {
|
||||
prop: 'checked',
|
||||
},
|
||||
computed: {
|
||||
hasDefaultSlot () {
|
||||
return !!this.$slots.default
|
||||
},
|
||||
classes () {
|
||||
const { prefixCls, disabled, checked } = this
|
||||
return {
|
||||
[`${prefixCls}-wrapper`]: true,
|
||||
[`${prefixCls}-wrapper-checked`]: checked,
|
||||
[`${prefixCls}-wrapper-disabled`]: disabled,
|
||||
}
|
||||
},
|
||||
checkboxClass () {
|
||||
const { prefixCls, disabled, checked } = this
|
||||
return {
|
||||
[`${prefixCls}`]: true,
|
||||
[`${prefixCls}-checked`]: checked,
|
||||
[`${prefixCls}-disabled`]: disabled,
|
||||
}
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
handleChange (event) {
|
||||
const { name, value } = this
|
||||
this.$emit('input', true)
|
||||
const target = {
|
||||
name,
|
||||
value,
|
||||
checked: true,
|
||||
}
|
||||
this.$emit('change', {
|
||||
target,
|
||||
stopPropagation () {
|
||||
event.stopPropagation()
|
||||
},
|
||||
preventDefault () {
|
||||
event.preventDefault()
|
||||
},
|
||||
})
|
||||
if (this.isGroup) {
|
||||
this.onGroupChange({ target })
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
0
components/radio/RadioButton.vue
Normal file
0
components/radio/RadioButton.vue
Normal file
6
components/radio/index.js
Normal file
6
components/radio/index.js
Normal file
@ -0,0 +1,6 @@
|
||||
import Radio from './Radio.vue'
|
||||
import RadioGroup from './Group.vue'
|
||||
|
||||
Radio.Group = RadioGroup
|
||||
export default Radio
|
||||
|
2
components/radio/style/index.js
Normal file
2
components/radio/style/index.js
Normal file
@ -0,0 +1,2 @@
|
||||
import '../../style/index.less'
|
||||
import './index.less'
|
279
components/radio/style/index.less
Normal file
279
components/radio/style/index.less
Normal file
@ -0,0 +1,279 @@
|
||||
@import "../../style/themes/default";
|
||||
@import "../../style/mixins/index";
|
||||
|
||||
@radio-prefix-cls: ~"@{ant-prefix}-radio";
|
||||
@radio-group-prefix-cls: ~"@{radio-prefix-cls}-group";
|
||||
@radio-inner-prefix-cls: ~"@{radio-prefix-cls}-inner";
|
||||
@radio-duration: .3s;
|
||||
|
||||
.@{radio-group-prefix-cls} {
|
||||
display: inline-block;
|
||||
font-size: @font-size-base;
|
||||
}
|
||||
|
||||
// 一般状态
|
||||
.@{radio-prefix-cls}-wrapper {
|
||||
font-size: @font-size-base;
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
white-space: nowrap;
|
||||
margin-right: 8px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.@{radio-prefix-cls} {
|
||||
white-space: nowrap;
|
||||
outline: none;
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
line-height: 1;
|
||||
vertical-align: text-bottom;
|
||||
cursor: pointer;
|
||||
.@{radio-prefix-cls}-wrapper:hover &,
|
||||
&:hover,
|
||||
&-focused {
|
||||
.@{radio-inner-prefix-cls} {
|
||||
border-color: @primary-color;
|
||||
}
|
||||
}
|
||||
&-checked:after {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border-radius: 50%;
|
||||
border: 1px solid @primary-color;
|
||||
content: '';
|
||||
animation: antRadioEffect 0.36s ease-in-out;
|
||||
animation-fill-mode: both;
|
||||
visibility: hidden;
|
||||
}
|
||||
&:hover:after,
|
||||
.@{radio-prefix-cls}-wrapper:hover &:after {
|
||||
visibility: visible;
|
||||
}
|
||||
&-inner {
|
||||
&:after {
|
||||
position: absolute;
|
||||
width: 6px;
|
||||
height: 6px;
|
||||
left: 3px;
|
||||
top: 3px;
|
||||
border-radius: @border-radius-base;
|
||||
display: table;
|
||||
border-top: 0;
|
||||
border-left: 0;
|
||||
content: ' ';
|
||||
background-color: @primary-color;
|
||||
opacity: 0;
|
||||
transform: scale(0);
|
||||
transition: all @radio-duration @ease-in-out-circ;
|
||||
}
|
||||
|
||||
position: relative;
|
||||
top: 0;
|
||||
left: 0;
|
||||
display: block;
|
||||
width: 14px;
|
||||
height: 14px;
|
||||
border-width: 1px;
|
||||
border-style: solid;
|
||||
border-radius: 14px;
|
||||
border-color: @border-color-base;
|
||||
background-color: @radio-button-bg;
|
||||
transition: all @radio-duration;
|
||||
}
|
||||
|
||||
&-input {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
z-index: 1;
|
||||
cursor: pointer;
|
||||
opacity: 0;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
}
|
||||
}
|
||||
|
||||
// 选中状态
|
||||
.@{radio-prefix-cls}-checked {
|
||||
.@{radio-inner-prefix-cls} {
|
||||
border-color: @primary-color;
|
||||
&:after {
|
||||
transform: scale(1);
|
||||
opacity: 1;
|
||||
transition: all @radio-duration @ease-in-out-circ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.@{radio-prefix-cls}-disabled {
|
||||
.@{radio-inner-prefix-cls} {
|
||||
border-color: @border-color-base !important;
|
||||
background-color: @input-disabled-bg;
|
||||
&:after {
|
||||
background-color: #ccc;
|
||||
}
|
||||
}
|
||||
|
||||
.@{radio-prefix-cls}-input {
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
& + span {
|
||||
color: @disabled-color;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
}
|
||||
|
||||
span.@{radio-prefix-cls} + * {
|
||||
padding-left: 8px;
|
||||
padding-right: 8px;
|
||||
}
|
||||
|
||||
.@{radio-prefix-cls}-button-wrapper {
|
||||
margin: 0;
|
||||
height: @input-height-base;
|
||||
line-height: @input-height-base - 2px;
|
||||
color: @radio-button-color;
|
||||
display: inline-block;
|
||||
transition: all 0.3s ease;
|
||||
cursor: pointer;
|
||||
border: @border-width-base @border-style-base @border-color-base;
|
||||
border-left: 0;
|
||||
background: @radio-button-bg;
|
||||
padding: 0 16px;
|
||||
position: relative;
|
||||
|
||||
a {
|
||||
color: @radio-button-color;
|
||||
}
|
||||
|
||||
> .@{radio-prefix-cls}-button {
|
||||
margin-left: 0;
|
||||
display: block;
|
||||
width: 0;
|
||||
height: 0;
|
||||
}
|
||||
|
||||
.@{radio-group-prefix-cls}-large & {
|
||||
height: @input-height-lg;
|
||||
line-height: @input-height-lg - 2px;
|
||||
}
|
||||
|
||||
.@{radio-group-prefix-cls}-small & {
|
||||
height: @input-height-sm;
|
||||
line-height: @input-height-sm - 2px;
|
||||
padding: 0 12px;
|
||||
&:first-child {
|
||||
border-radius: @border-radius-sm 0 0 @border-radius-sm;
|
||||
}
|
||||
&:last-child {
|
||||
border-radius: 0 @border-radius-sm @border-radius-sm 0;
|
||||
}
|
||||
}
|
||||
|
||||
&:not(:first-child) {
|
||||
&::before {
|
||||
content: "";
|
||||
display: block;
|
||||
top: 0;
|
||||
left: -1px;
|
||||
width: 1px;
|
||||
height: 100%;
|
||||
position: absolute;
|
||||
background-color: @border-color-base;
|
||||
}
|
||||
}
|
||||
&:first-child {
|
||||
border-radius: @border-radius-base 0 0 @border-radius-base;
|
||||
border-left: @border-width-base @border-style-base @border-color-base;
|
||||
}
|
||||
|
||||
&:last-child {
|
||||
border-radius: 0 @border-radius-base @border-radius-base 0;
|
||||
}
|
||||
|
||||
&:first-child:last-child {
|
||||
border-radius: @border-radius-base;
|
||||
}
|
||||
|
||||
&:hover,
|
||||
&-focused {
|
||||
color: @primary-color;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.@{radio-prefix-cls}-inner,
|
||||
input[type="checkbox"],
|
||||
input[type="radio"] {
|
||||
.opacity(0);
|
||||
width: 0;
|
||||
height: 0;
|
||||
}
|
||||
|
||||
&-checked {
|
||||
background: @radio-button-bg;
|
||||
border-color: @primary-color;
|
||||
color: @primary-color;
|
||||
box-shadow: -1px 0 0 0 @primary-color;
|
||||
z-index: 1;
|
||||
&::before {
|
||||
background-color: @primary-color !important;
|
||||
opacity: 0.1;
|
||||
}
|
||||
&:first-child {
|
||||
border-color: @primary-color;
|
||||
box-shadow: none !important;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
border-color: @primary-5;
|
||||
box-shadow: -1px 0 0 0 @primary-5;
|
||||
color: @primary-5;
|
||||
}
|
||||
|
||||
&:active {
|
||||
border-color: @primary-7;
|
||||
box-shadow: -1px 0 0 0 @primary-7;
|
||||
color: @primary-7;
|
||||
}
|
||||
}
|
||||
|
||||
&-disabled {
|
||||
border-color: @border-color-base;
|
||||
background-color: @input-disabled-bg;
|
||||
cursor: not-allowed;
|
||||
color: @disabled-color;
|
||||
|
||||
&:first-child,
|
||||
&:hover {
|
||||
border-color: @border-color-base;
|
||||
background-color: @input-disabled-bg;
|
||||
color: @disabled-color;
|
||||
}
|
||||
&:first-child {
|
||||
border-left-color: @border-color-base;
|
||||
}
|
||||
}
|
||||
|
||||
&-disabled&-checked {
|
||||
color: #fff;
|
||||
background-color: #e6e6e6;
|
||||
border-color: @border-color-base;
|
||||
box-shadow: none;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes antRadioEffect {
|
||||
0% {
|
||||
transform: scale(1);
|
||||
opacity: 0.5;
|
||||
}
|
||||
100% {
|
||||
transform: scale(1.6);
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<div>
|
||||
<Checkbox :indeterminate="true" @change="change" name="test" value="123" />
|
||||
<Checkbox :checked="true" @change="change" name="test" value="123" />
|
||||
<Checkbox @change="change" v-model="checked" name="test" value="123">Checkbox</Checkbox>
|
||||
<Checkbox :disabled="true" @change="change" v-model="checked" name="test2" value="222">Checkbox</Checkbox>
|
||||
|
||||
|
@ -1,12 +1,14 @@
|
||||
import Vue from 'vue'
|
||||
import Checkbox from './checkbox.vue'
|
||||
import Button from './button.vue'
|
||||
import Radio from './radio.vue'
|
||||
// import Dialog from './dialog.vue'
|
||||
import './index.less'
|
||||
new Vue({
|
||||
el: '#app',
|
||||
template: `
|
||||
<div>
|
||||
<Radio />
|
||||
<Checkbox />
|
||||
<AntButton />
|
||||
</div>
|
||||
@ -15,5 +17,6 @@ new Vue({
|
||||
AntButton: Button,
|
||||
// AntDialog: Dialog,
|
||||
Checkbox,
|
||||
Radio,
|
||||
},
|
||||
})
|
||||
|
52
examples/radio.vue
Normal file
52
examples/radio.vue
Normal file
@ -0,0 +1,52 @@
|
||||
<template>
|
||||
<div>
|
||||
<Radio v-model="checked" @change="change" name="test" value="123">Radio</Radio>
|
||||
<Radio :checked="false" @change="change" name="test2" value="222">Radio</Radio>
|
||||
|
||||
<RadioGroup v-model="value" @change="change">
|
||||
<AntButton @click="handleAddClick">
|
||||
{{showMore ? "删除": "添加"}}
|
||||
</AntButton>
|
||||
<Radio name="test1" value="1">Radio1</Radio>
|
||||
<Radio name="test2" value="2" disabled>Radio2</Radio>
|
||||
<Radio name="test3" value="3" @change="change">Radio3</Radio>
|
||||
<Radio v-if="showMore" name="test4" value="4">Radio4</Radio>
|
||||
</RadioGroup>
|
||||
<RadioGroup :options="options" v-model="value1" @change="change"></RadioGroup>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import { Button, Radio } from '../components/index'
|
||||
export default {
|
||||
data () {
|
||||
return {
|
||||
visible: true,
|
||||
checked: false,
|
||||
options: [
|
||||
{ label: 'Apple', value: 'Apple' },
|
||||
{ label: 'Pear', value: 'Pear' },
|
||||
{ label: 'Orange', value: 'Orange', disabled: true },
|
||||
],
|
||||
value: '1',
|
||||
value1: '',
|
||||
showMore: false,
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
change (event) {
|
||||
console.log(event)
|
||||
},
|
||||
handleClick () {
|
||||
this.value = ['1', '2', '3']
|
||||
},
|
||||
handleAddClick () {
|
||||
this.showMore = !this.showMore
|
||||
},
|
||||
},
|
||||
components: {
|
||||
Radio,
|
||||
RadioGroup: Radio.Group,
|
||||
AntButton: Button,
|
||||
},
|
||||
}
|
||||
</script>
|
Loading…
Reference in New Issue
Block a user