Commit cbe03a12b2f4a79311b6e7a95d13811ae3a41a92
1 parent
06322514
support Checkbox
support Checkbox
Showing
10 changed files
with
146 additions
and
29 deletions
Show diff stats
CHANGE.md
| @@ -4,3 +4,7 @@ | @@ -4,3 +4,7 @@ | ||
| 4 | 使用 v-model | 4 | 使用 v-model |
| 5 | ### Radio | 5 | ### Radio |
| 6 | value 改为了 label,使用 v-model,废弃 checked | 6 | value 改为了 label,使用 v-model,废弃 checked |
| 7 | +### Checkbox | ||
| 8 | +使用 v-model | ||
| 9 | +### CheckboxGroup | ||
| 10 | +value 改为了 label,使用 v-model,废弃 checked | ||
| 7 | \ No newline at end of file | 11 | \ No newline at end of file |
README.md
src/components/checkbox/checkbox-group.vue
| @@ -9,42 +9,49 @@ | @@ -9,42 +9,49 @@ | ||
| 9 | export default { | 9 | export default { |
| 10 | name: 'checkboxGroup', | 10 | name: 'checkboxGroup', |
| 11 | props: { | 11 | props: { |
| 12 | - model: { | 12 | + value: { |
| 13 | type: Array, | 13 | type: Array, |
| 14 | default () { | 14 | default () { |
| 15 | return []; | 15 | return []; |
| 16 | } | 16 | } |
| 17 | } | 17 | } |
| 18 | }, | 18 | }, |
| 19 | + data () { | ||
| 20 | + return { | ||
| 21 | + currentValue: this.value | ||
| 22 | + }; | ||
| 23 | + }, | ||
| 19 | computed: { | 24 | computed: { |
| 20 | classes () { | 25 | classes () { |
| 21 | return `${prefixCls}`; | 26 | return `${prefixCls}`; |
| 22 | } | 27 | } |
| 23 | }, | 28 | }, |
| 24 | - compiled () { | 29 | + mounted () { |
| 25 | this.updateModel(true); | 30 | this.updateModel(true); |
| 26 | }, | 31 | }, |
| 27 | methods: { | 32 | methods: { |
| 28 | updateModel (update) { | 33 | updateModel (update) { |
| 29 | - const model = this.model; | 34 | + const value = this.value; |
| 30 | 35 | ||
| 31 | this.$children.forEach((child) => { | 36 | this.$children.forEach((child) => { |
| 32 | - child.model = model; | 37 | + child.model = value; |
| 33 | 38 | ||
| 34 | if (update) { | 39 | if (update) { |
| 35 | - child.selected = model.indexOf(child.value) >= 0; | 40 | + child.currentValue = value.indexOf(child.label) >= 0; |
| 36 | child.group = true; | 41 | child.group = true; |
| 37 | } | 42 | } |
| 38 | }); | 43 | }); |
| 39 | }, | 44 | }, |
| 40 | change (data) { | 45 | change (data) { |
| 41 | - this.model = data; | 46 | + this.currentValue = data; |
| 47 | + this.$emit('input', data); | ||
| 42 | this.$emit('on-change', data); | 48 | this.$emit('on-change', data); |
| 43 | - this.$dispatch('on-form-change', data); | 49 | + // todo 事件 |
| 50 | +// this.$dispatch('on-form-change', data); | ||
| 44 | } | 51 | } |
| 45 | }, | 52 | }, |
| 46 | watch: { | 53 | watch: { |
| 47 | - model () { | 54 | + value () { |
| 48 | this.updateModel(true); | 55 | this.updateModel(true); |
| 49 | } | 56 | } |
| 50 | } | 57 | } |
src/components/checkbox/checkbox.vue
| @@ -7,7 +7,7 @@ | @@ -7,7 +7,7 @@ | ||
| 7 | type="checkbox" | 7 | type="checkbox" |
| 8 | :class="inputClasses" | 8 | :class="inputClasses" |
| 9 | :disabled="disabled" | 9 | :disabled="disabled" |
| 10 | - :value="value" | 10 | + :value="label" |
| 11 | v-model="model" | 11 | v-model="model" |
| 12 | @change="change"> | 12 | @change="change"> |
| 13 | <input | 13 | <input |
| @@ -15,28 +15,29 @@ | @@ -15,28 +15,29 @@ | ||
| 15 | type="checkbox" | 15 | type="checkbox" |
| 16 | :class="inputClasses" | 16 | :class="inputClasses" |
| 17 | :disabled="disabled" | 17 | :disabled="disabled" |
| 18 | - v-model="checked" | 18 | + :checked="currentValue" |
| 19 | @change="change"> | 19 | @change="change"> |
| 20 | </span> | 20 | </span> |
| 21 | - <slot v-if="showSlot"><span v-el:slot>{{ value }}</span></slot> | 21 | + <slot v-if="showSlot"><span ref="slot">{{ label }}</span></slot> |
| 22 | </label> | 22 | </label> |
| 23 | </template> | 23 | </template> |
| 24 | <script> | 24 | <script> |
| 25 | const prefixCls = 'ivu-checkbox'; | 25 | const prefixCls = 'ivu-checkbox'; |
| 26 | 26 | ||
| 27 | export default { | 27 | export default { |
| 28 | + name: 'Checkbox', | ||
| 28 | props: { | 29 | props: { |
| 29 | disabled: { | 30 | disabled: { |
| 30 | type: Boolean, | 31 | type: Boolean, |
| 31 | default: false | 32 | default: false |
| 32 | }, | 33 | }, |
| 33 | value: { | 34 | value: { |
| 34 | - type: [String, Number, Boolean] | ||
| 35 | - }, | ||
| 36 | - checked: { | ||
| 37 | type: Boolean, | 35 | type: Boolean, |
| 38 | default: false | 36 | default: false |
| 39 | }, | 37 | }, |
| 38 | + label: { | ||
| 39 | + type: [String, Number, Boolean] | ||
| 40 | + }, | ||
| 40 | indeterminate: { | 41 | indeterminate: { |
| 41 | type: Boolean, | 42 | type: Boolean, |
| 42 | default: false | 43 | default: false |
| @@ -45,7 +46,7 @@ | @@ -45,7 +46,7 @@ | ||
| 45 | data () { | 46 | data () { |
| 46 | return { | 47 | return { |
| 47 | model: [], | 48 | model: [], |
| 48 | - selected: false, | 49 | + currentValue: this.value, |
| 49 | group: false, | 50 | group: false, |
| 50 | showSlot: true | 51 | showSlot: true |
| 51 | }; | 52 | }; |
| @@ -56,7 +57,7 @@ | @@ -56,7 +57,7 @@ | ||
| 56 | `${prefixCls}-wrapper`, | 57 | `${prefixCls}-wrapper`, |
| 57 | { | 58 | { |
| 58 | [`${prefixCls}-group-item`]: this.group, | 59 | [`${prefixCls}-group-item`]: this.group, |
| 59 | - [`${prefixCls}-wrapper-checked`]: this.selected, | 60 | + [`${prefixCls}-wrapper-checked`]: this.currentValue, |
| 60 | [`${prefixCls}-wrapper-disabled`]: this.disabled | 61 | [`${prefixCls}-wrapper-disabled`]: this.disabled |
| 61 | } | 62 | } |
| 62 | ]; | 63 | ]; |
| @@ -65,7 +66,7 @@ | @@ -65,7 +66,7 @@ | ||
| 65 | return [ | 66 | return [ |
| 66 | `${prefixCls}`, | 67 | `${prefixCls}`, |
| 67 | { | 68 | { |
| 68 | - [`${prefixCls}-checked`]: this.selected, | 69 | + [`${prefixCls}-checked`]: this.currentValue, |
| 69 | [`${prefixCls}-disabled`]: this.disabled, | 70 | [`${prefixCls}-disabled`]: this.disabled, |
| 70 | [`${prefixCls}-indeterminate`]: this.indeterminate | 71 | [`${prefixCls}-indeterminate`]: this.indeterminate |
| 71 | } | 72 | } |
| @@ -78,11 +79,12 @@ | @@ -78,11 +79,12 @@ | ||
| 78 | return `${prefixCls}-input`; | 79 | return `${prefixCls}-input`; |
| 79 | } | 80 | } |
| 80 | }, | 81 | }, |
| 81 | - ready () { | 82 | + mounted () { |
| 83 | + // todo 使用 while向上查找 | ||
| 82 | if (this.$parent && this.$parent.$options.name === 'checkboxGroup') this.group = true; | 84 | if (this.$parent && this.$parent.$options.name === 'checkboxGroup') this.group = true; |
| 83 | if (!this.group) { | 85 | if (!this.group) { |
| 84 | this.updateModel(); | 86 | this.updateModel(); |
| 85 | - if (this.$els.slot && this.$els.slot.innerHTML === '') { | 87 | + if (this.$refs.slot && this.$refs.slot.innerHTML === '') { |
| 86 | this.showSlot = false; | 88 | this.showSlot = false; |
| 87 | } | 89 | } |
| 88 | } | 90 | } |
| @@ -93,21 +95,24 @@ | @@ -93,21 +95,24 @@ | ||
| 93 | return false; | 95 | return false; |
| 94 | } | 96 | } |
| 95 | 97 | ||
| 96 | - this.selected = event.target.checked; | 98 | + const checked = event.target.checked; |
| 99 | + this.currentValue = checked; | ||
| 100 | + this.$emit('input', checked); | ||
| 97 | 101 | ||
| 98 | if (this.group) { | 102 | if (this.group) { |
| 99 | this.$parent.change(this.model); | 103 | this.$parent.change(this.model); |
| 100 | } else { | 104 | } else { |
| 101 | - this.$emit('on-change', this.checked); | ||
| 102 | - this.$dispatch('on-form-change', this.checked); | 105 | + this.$emit('on-change', checked); |
| 106 | + // todo 事件 | ||
| 107 | +// this.$dispatch('on-form-change', checked); | ||
| 103 | } | 108 | } |
| 104 | }, | 109 | }, |
| 105 | updateModel () { | 110 | updateModel () { |
| 106 | - this.selected = this.checked; | 111 | + this.currentValue = this.value; |
| 107 | } | 112 | } |
| 108 | }, | 113 | }, |
| 109 | watch: { | 114 | watch: { |
| 110 | - checked () { | 115 | + value () { |
| 111 | this.updateModel(); | 116 | this.updateModel(); |
| 112 | } | 117 | } |
| 113 | } | 118 | } |
src/components/radio/radio-group.vue
src/components/radio/radio.vue
| @@ -63,6 +63,7 @@ | @@ -63,6 +63,7 @@ | ||
| 63 | } | 63 | } |
| 64 | }, | 64 | }, |
| 65 | mounted () { | 65 | mounted () { |
| 66 | + // todo 使用 while向上查找 | ||
| 66 | if (this.$parent && this.$parent.$options.name === 'radioGroup') this.group = true; | 67 | if (this.$parent && this.$parent.$options.name === 'radioGroup') this.group = true; |
| 67 | if (!this.group) { | 68 | if (!this.group) { |
| 68 | this.updateValue(); | 69 | this.updateValue(); |
src/index.js
| @@ -10,7 +10,7 @@ import Button from './components/button'; | @@ -10,7 +10,7 @@ import Button from './components/button'; | ||
| 10 | // import Card from './components/card'; | 10 | // import Card from './components/card'; |
| 11 | // import Carousel from './components/carousel'; | 11 | // import Carousel from './components/carousel'; |
| 12 | // import Cascader from './components/cascader'; | 12 | // import Cascader from './components/cascader'; |
| 13 | -// import Checkbox from './components/checkbox'; | 13 | +import Checkbox from './components/checkbox'; |
| 14 | // import Circle from './components/circle'; | 14 | // import Circle from './components/circle'; |
| 15 | // import Collapse from './components/collapse'; | 15 | // import Collapse from './components/collapse'; |
| 16 | // import DatePicker from './components/date-picker'; | 16 | // import DatePicker from './components/date-picker'; |
| @@ -60,8 +60,8 @@ const iview = { | @@ -60,8 +60,8 @@ const iview = { | ||
| 60 | // Carousel, | 60 | // Carousel, |
| 61 | // CarouselItem: Carousel.Item, | 61 | // CarouselItem: Carousel.Item, |
| 62 | // Cascader, | 62 | // Cascader, |
| 63 | - // Checkbox, | ||
| 64 | - // CheckboxGroup: Checkbox.Group, | 63 | + Checkbox, |
| 64 | + CheckboxGroup: Checkbox.Group, | ||
| 65 | // Circle, | 65 | // Circle, |
| 66 | // DatePicker, | 66 | // DatePicker, |
| 67 | // Dropdown, | 67 | // Dropdown, |
test/app.vue
| @@ -29,6 +29,7 @@ li + li { | @@ -29,6 +29,7 @@ li + li { | ||
| 29 | <li><router-link to="/button">Button</router-link></li> | 29 | <li><router-link to="/button">Button</router-link></li> |
| 30 | <li><router-link to="/input">Input</router-link></li> | 30 | <li><router-link to="/input">Input</router-link></li> |
| 31 | <li><router-link to="/radio">Radio</router-link></li> | 31 | <li><router-link to="/radio">Radio</router-link></li> |
| 32 | + <li><router-link to="/checkbox">Checkbox</router-link></li> | ||
| 32 | </ul> | 33 | </ul> |
| 33 | </nav> | 34 | </nav> |
| 34 | <router-view></router-view> | 35 | <router-view></router-view> |
test/main.js
| @@ -36,6 +36,10 @@ const router = new VueRouter({ | @@ -36,6 +36,10 @@ const router = new VueRouter({ | ||
| 36 | { | 36 | { |
| 37 | path: '/radio', | 37 | path: '/radio', |
| 38 | component: require('./routers/radio.vue') | 38 | component: require('./routers/radio.vue') |
| 39 | + }, | ||
| 40 | + { | ||
| 41 | + path: '/checkbox', | ||
| 42 | + component: require('./routers/checkbox.vue') | ||
| 39 | } | 43 | } |
| 40 | ] | 44 | ] |
| 41 | }); | 45 | }); |
| 1 | +<template> | ||
| 2 | + <div> | ||
| 3 | + <Checkbox v-model="single" @on-change="s">Checkbox</Checkbox> | ||
| 4 | + {{ single }} | ||
| 5 | + <div @click="single = !single">single-change</div> | ||
| 6 | + <br> | ||
| 7 | + {{ social }} | ||
| 8 | + <Checkbox-group v-model="social" @on-change="s"> | ||
| 9 | + <Checkbox label="twitter"> | ||
| 10 | + <Icon type="social-twitter"></Icon> | ||
| 11 | + <span>Twitter</span> | ||
| 12 | + </Checkbox> | ||
| 13 | + <Checkbox label="facebook"> | ||
| 14 | + <Icon type="social-facebook"></Icon> | ||
| 15 | + <span>Facebook</span> | ||
| 16 | + </Checkbox> | ||
| 17 | + <Checkbox label="github"> | ||
| 18 | + <Icon type="social-github"></Icon> | ||
| 19 | + <span>Github</span> | ||
| 20 | + </Checkbox> | ||
| 21 | + <Checkbox label="snapchat"> | ||
| 22 | + <Icon type="social-snapchat"></Icon> | ||
| 23 | + <span>Snapchat</span> | ||
| 24 | + </Checkbox> | ||
| 25 | + </Checkbox-group> | ||
| 26 | + <br> | ||
| 27 | + <div @click="c">修改1</div> | ||
| 28 | + {{ fruit }} | ||
| 29 | + <Checkbox-group v-model="fruit"> | ||
| 30 | + <Checkbox label="香蕉"></Checkbox> | ||
| 31 | + <Checkbox label="苹果"></Checkbox> | ||
| 32 | + <Checkbox label="西瓜"></Checkbox> | ||
| 33 | + </Checkbox-group> | ||
| 34 | + <br><br> | ||
| 35 | + <div style="border-bottom: 1px solid #e9e9e9;padding-bottom:6px;margin-bottom:6px;"> | ||
| 36 | + <Checkbox | ||
| 37 | + :indeterminate="indeterminate" | ||
| 38 | + v-model="checkAll" | ||
| 39 | + @click.prevent.native="handleCheckAll">全选</Checkbox> | ||
| 40 | + </div> | ||
| 41 | + <Checkbox-group v-model="checkAllGroup" @on-change="checkAllGroupChange"> | ||
| 42 | + <Checkbox label="香蕉"></Checkbox> | ||
| 43 | + <Checkbox label="苹果"></Checkbox> | ||
| 44 | + <Checkbox label="西瓜"></Checkbox> | ||
| 45 | + </Checkbox-group> | ||
| 46 | + </div> | ||
| 47 | +</template> | ||
| 48 | +<script> | ||
| 49 | + export default { | ||
| 50 | + data () { | ||
| 51 | + return { | ||
| 52 | + social: ['facebook', 'github'], | ||
| 53 | + fruit: ['苹果'], | ||
| 54 | + single: false, | ||
| 55 | + indeterminate: true, | ||
| 56 | + checkAll: false, | ||
| 57 | + checkAllGroup: ['香蕉', '西瓜'] | ||
| 58 | + } | ||
| 59 | + }, | ||
| 60 | + methods: { | ||
| 61 | + c () { | ||
| 62 | + this.social.splice(0, 1) | ||
| 63 | + }, | ||
| 64 | + s (d) { | ||
| 65 | + console.log(d) | ||
| 66 | + }, | ||
| 67 | + handleCheckAll () { | ||
| 68 | + if (this.indeterminate) { | ||
| 69 | + this.checkAll = false; | ||
| 70 | + } else { | ||
| 71 | + this.checkAll = !this.checkAll; | ||
| 72 | + } | ||
| 73 | + this.indeterminate = false; | ||
| 74 | + | ||
| 75 | + if (this.checkAll) { | ||
| 76 | + this.checkAllGroup = ['香蕉', '苹果', '西瓜']; | ||
| 77 | + } else { | ||
| 78 | + this.checkAllGroup = []; | ||
| 79 | + } | ||
| 80 | + }, | ||
| 81 | + checkAllGroupChange (data) { | ||
| 82 | + if (data.length === 3) { | ||
| 83 | + this.indeterminate = false; | ||
| 84 | + this.checkAll = true; | ||
| 85 | + } else if (data.length > 0) { | ||
| 86 | + this.indeterminate = true; | ||
| 87 | + this.checkAll = false; | ||
| 88 | + } else { | ||
| 89 | + this.indeterminate = false; | ||
| 90 | + this.checkAll = false; | ||
| 91 | + } | ||
| 92 | + } | ||
| 93 | + } | ||
| 94 | + } | ||
| 95 | +</script> |