This commit is contained in:
tangjinzhou 2017-10-27 14:04:48 +08:00
parent 9ec6439cca
commit 82c46afe9e
13 changed files with 509 additions and 11 deletions

View File

@ -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',
},

View File

@ -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

View File

@ -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

View File

@ -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'

View 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>

View 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>

View File

View File

@ -0,0 +1,6 @@
import Radio from './Radio.vue'
import RadioGroup from './Group.vue'
Radio.Group = RadioGroup
export default Radio

View File

@ -0,0 +1,2 @@
import '../../style/index.less'
import './index.less'

View 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;
}
}

View File

@ -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>

View File

@ -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
View 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>