Commit 23646cc575031d5117b6588214870464fb148dbe
Committed by
GitHub
Merge pull request #2868 from Xotic750/checkbox_tabindex
Checkbox w3c
Showing
4 changed files
with
43 additions
and
33 deletions
Show diff stats
examples/routers/checkbox.vue
| @@ -37,7 +37,7 @@ | @@ -37,7 +37,7 @@ | ||
| 37 | tags: [], | 37 | tags: [], |
| 38 | testValue1: null, | 38 | testValue1: null, |
| 39 | testValue2: null | 39 | testValue2: null |
| 40 | - } | 40 | + }; |
| 41 | }, | 41 | }, |
| 42 | mounted () { | 42 | mounted () { |
| 43 | setTimeout(() => { | 43 | setTimeout(() => { |
| @@ -51,8 +51,8 @@ | @@ -51,8 +51,8 @@ | ||
| 51 | { | 51 | { |
| 52 | label: '西瓜' | 52 | label: '西瓜' |
| 53 | } | 53 | } |
| 54 | - ] | 54 | + ]; |
| 55 | }, 1000); | 55 | }, 1000); |
| 56 | } | 56 | } |
| 57 | - } | 57 | + }; |
| 58 | </script> | 58 | </script> |
src/components/checkbox/checkbox-group.vue
| @@ -6,6 +6,7 @@ | @@ -6,6 +6,7 @@ | ||
| 6 | <script> | 6 | <script> |
| 7 | import { findComponentsDownward, oneOf } from '../../utils/assist'; | 7 | import { findComponentsDownward, oneOf } from '../../utils/assist'; |
| 8 | import Emitter from '../../mixins/emitter'; | 8 | import Emitter from '../../mixins/emitter'; |
| 9 | + | ||
| 9 | const prefixCls = 'ivu-checkbox-group'; | 10 | const prefixCls = 'ivu-checkbox-group'; |
| 10 | 11 | ||
| 11 | export default { | 12 | export default { |
| @@ -45,10 +46,9 @@ | @@ -45,10 +46,9 @@ | ||
| 45 | }, | 46 | }, |
| 46 | methods: { | 47 | methods: { |
| 47 | updateModel (update) { | 48 | updateModel (update) { |
| 48 | - const value = this.value; | ||
| 49 | this.childrens = findComponentsDownward(this, 'Checkbox'); | 49 | this.childrens = findComponentsDownward(this, 'Checkbox'); |
| 50 | - | ||
| 51 | if (this.childrens) { | 50 | if (this.childrens) { |
| 51 | + const { value } = this; | ||
| 52 | this.childrens.forEach(child => { | 52 | this.childrens.forEach(child => { |
| 53 | child.model = value; | 53 | child.model = value; |
| 54 | 54 |
src/components/checkbox/checkbox.vue
| 1 | <template> | 1 | <template> |
| 2 | - <label | ||
| 3 | - :class="wrapClasses" | ||
| 4 | - @keydown.space.prevent="$el.click()" | ||
| 5 | - :tabindex="disabled ? -1 : 0"> | 2 | + <label :class="wrapClasses"> |
| 6 | <span :class="checkboxClasses"> | 3 | <span :class="checkboxClasses"> |
| 7 | <span :class="innerClasses"></span> | 4 | <span :class="innerClasses"></span> |
| 8 | <input | 5 | <input |
| 9 | v-if="group" | 6 | v-if="group" |
| 10 | type="checkbox" | 7 | type="checkbox" |
| 11 | - tabindex="-1" | ||
| 12 | :class="inputClasses" | 8 | :class="inputClasses" |
| 13 | :disabled="disabled" | 9 | :disabled="disabled" |
| 14 | :value="label" | 10 | :value="label" |
| 15 | v-model="model" | 11 | v-model="model" |
| 16 | :name="name" | 12 | :name="name" |
| 17 | @change="change" | 13 | @change="change" |
| 18 | - @focus="$el.focus()" | ||
| 19 | - > | 14 | + @focus="onFocus" |
| 15 | + @blur="onBlur"> | ||
| 20 | <input | 16 | <input |
| 21 | - v-if="!group" | 17 | + v-else |
| 22 | type="checkbox" | 18 | type="checkbox" |
| 23 | - tabindex="-1" | ||
| 24 | :class="inputClasses" | 19 | :class="inputClasses" |
| 25 | :disabled="disabled" | 20 | :disabled="disabled" |
| 26 | :checked="currentValue" | 21 | :checked="currentValue" |
| 27 | :name="name" | 22 | :name="name" |
| 28 | @change="change" | 23 | @change="change" |
| 29 | - @focus="$el.focus()" | ||
| 30 | - > | 24 | + @focus="onFocus" |
| 25 | + @blur="onBlur"> | ||
| 31 | </span> | 26 | </span> |
| 32 | <slot><span v-if="showSlot">{{ label }}</span></slot> | 27 | <slot><span v-if="showSlot">{{ label }}</span></slot> |
| 33 | </label> | 28 | </label> |
| @@ -80,7 +75,8 @@ | @@ -80,7 +75,8 @@ | ||
| 80 | currentValue: this.value, | 75 | currentValue: this.value, |
| 81 | group: false, | 76 | group: false, |
| 82 | showSlot: true, | 77 | showSlot: true, |
| 83 | - parent: findComponentUpward(this, 'CheckboxGroup') | 78 | + parent: findComponentUpward(this, 'CheckboxGroup'), |
| 79 | + focusInner: false | ||
| 84 | }; | 80 | }; |
| 85 | }, | 81 | }, |
| 86 | computed: { | 82 | computed: { |
| @@ -106,7 +102,12 @@ | @@ -106,7 +102,12 @@ | ||
| 106 | ]; | 102 | ]; |
| 107 | }, | 103 | }, |
| 108 | innerClasses () { | 104 | innerClasses () { |
| 109 | - return `${prefixCls}-inner`; | 105 | + return [ |
| 106 | + `${prefixCls}-inner`, | ||
| 107 | + { | ||
| 108 | + [`${prefixCls}-focus`]: this.focusInner | ||
| 109 | + } | ||
| 110 | + ]; | ||
| 110 | }, | 111 | }, |
| 111 | inputClasses () { | 112 | inputClasses () { |
| 112 | return `${prefixCls}-input`; | 113 | return `${prefixCls}-input`; |
| @@ -114,12 +115,15 @@ | @@ -114,12 +115,15 @@ | ||
| 114 | }, | 115 | }, |
| 115 | mounted () { | 116 | mounted () { |
| 116 | this.parent = findComponentUpward(this, 'CheckboxGroup'); | 117 | this.parent = findComponentUpward(this, 'CheckboxGroup'); |
| 117 | - if (this.parent) this.group = true; | ||
| 118 | - if (!this.group) { | 118 | + if (this.parent) { |
| 119 | + this.group = true; | ||
| 120 | + } | ||
| 121 | + | ||
| 122 | + if (this.group) { | ||
| 123 | + this.parent.updateModel(true); | ||
| 124 | + } else { | ||
| 119 | this.updateModel(); | 125 | this.updateModel(); |
| 120 | this.showSlot = this.$slots.default !== undefined; | 126 | this.showSlot = this.$slots.default !== undefined; |
| 121 | - } else { | ||
| 122 | - this.parent.updateModel(true); | ||
| 123 | } | 127 | } |
| 124 | }, | 128 | }, |
| 125 | methods: { | 129 | methods: { |
| @@ -131,7 +135,7 @@ | @@ -131,7 +135,7 @@ | ||
| 131 | const checked = event.target.checked; | 135 | const checked = event.target.checked; |
| 132 | this.currentValue = checked; | 136 | this.currentValue = checked; |
| 133 | 137 | ||
| 134 | - let value = checked ? this.trueValue : this.falseValue; | 138 | + const value = checked ? this.trueValue : this.falseValue; |
| 135 | this.$emit('input', value); | 139 | this.$emit('input', value); |
| 136 | 140 | ||
| 137 | if (this.group) { | 141 | if (this.group) { |
| @@ -143,14 +147,21 @@ | @@ -143,14 +147,21 @@ | ||
| 143 | }, | 147 | }, |
| 144 | updateModel () { | 148 | updateModel () { |
| 145 | this.currentValue = this.value === this.trueValue; | 149 | this.currentValue = this.value === this.trueValue; |
| 150 | + }, | ||
| 151 | + onBlur () { | ||
| 152 | + this.focusInner = false; | ||
| 153 | + }, | ||
| 154 | + onFocus () { | ||
| 155 | + this.focusInner = true; | ||
| 146 | } | 156 | } |
| 147 | }, | 157 | }, |
| 148 | watch: { | 158 | watch: { |
| 149 | value (val) { | 159 | value (val) { |
| 150 | - if (val !== this.trueValue && val !== this.falseValue) { | 160 | + if (val === this.trueValue || val === this.falseValue) { |
| 161 | + this.updateModel(); | ||
| 162 | + } else { | ||
| 151 | throw 'Value should be trueValue or falseValue.'; | 163 | throw 'Value should be trueValue or falseValue.'; |
| 152 | } | 164 | } |
| 153 | - this.updateModel(); | ||
| 154 | } | 165 | } |
| 155 | } | 166 | } |
| 156 | }; | 167 | }; |
src/styles/mixins/checkbox.less
| 1 | .checkboxFn(@checkbox-prefix-cls: ~"@{css-prefix}checkbox") { | 1 | .checkboxFn(@checkbox-prefix-cls: ~"@{css-prefix}checkbox") { |
| 2 | @checkbox-inner-prefix-cls: ~"@{checkbox-prefix-cls}-inner"; | 2 | @checkbox-inner-prefix-cls: ~"@{checkbox-prefix-cls}-inner"; |
| 3 | 3 | ||
| 4 | + .@{checkbox-prefix-cls}-focus { | ||
| 5 | + box-shadow: 0 0 0 2px fade(@primary-color, 20%); | ||
| 6 | + z-index: 1; | ||
| 7 | + } | ||
| 8 | + | ||
| 4 | // 普通状态 | 9 | // 普通状态 |
| 5 | .@{checkbox-prefix-cls} { | 10 | .@{checkbox-prefix-cls} { |
| 6 | display: inline-block; | 11 | display: inline-block; |
| 7 | vertical-align: middle; | 12 | vertical-align: middle; |
| 8 | white-space: nowrap; | 13 | white-space: nowrap; |
| 9 | cursor: pointer; | 14 | cursor: pointer; |
| 10 | - outline: none; | 15 | + //outline: none; |
| 11 | line-height: 1; | 16 | line-height: 1; |
| 12 | position: relative; | 17 | position: relative; |
| 13 | 18 | ||
| @@ -236,13 +241,7 @@ | @@ -236,13 +241,7 @@ | ||
| 236 | font-size: @font-size-small; | 241 | font-size: @font-size-small; |
| 237 | display: inline-block; | 242 | display: inline-block; |
| 238 | margin-right: 8px; | 243 | margin-right: 8px; |
| 239 | - outline: 0; | ||
| 240 | - &:focus, | ||
| 241 | - &:active { | ||
| 242 | - & .@{checkbox-prefix-cls}-inner { | ||
| 243 | - box-shadow: 0 0 0 2px fade(@primary-color, 20%); | ||
| 244 | - } | ||
| 245 | - } | 244 | + //outline: none; |
| 246 | 245 | ||
| 247 | &-disabled{ | 246 | &-disabled{ |
| 248 | cursor: @cursor-disabled; | 247 | cursor: @cursor-disabled; |