Commit 342390e691f0a67379663cc315e882aef68c54a3

Authored by Aresn
Committed by GitHub
2 parents 105af4ee a646fc36

Merge pull request #2882 from iview/pr/2867

Pr/2867
examples/routers/radio.vue
@@ -43,12 +43,12 @@ @@ -43,12 +43,12 @@
43 data () { 43 data () {
44 return { 44 return {
45 single: true, 45 single: true,
46 - phone: 'apple', 46 + phone: '',
47 button2: '北京', 47 button2: '北京',
48 - } 48 + };
49 }, 49 },
50 methods: { 50 methods: {
51 51
52 } 52 }
53 - } 53 + };
54 </script> 54 </script>
src/components/radio/radio-group.vue
1 <template> 1 <template>
2 - <div :class="classes"> 2 + <div :class="classes" :name="name">
3 <slot></slot> 3 <slot></slot>
4 </div> 4 </div>
5 </template> 5 </template>
@@ -9,6 +9,10 @@ @@ -9,6 +9,10 @@
9 9
10 const prefixCls = 'ivu-radio-group'; 10 const prefixCls = 'ivu-radio-group';
11 11
  12 + let seed = 0;
  13 + const now = Date.now();
  14 + const getUuid = () => `ivuRadioGroup_${now}_${seed++}`;
  15 +
12 export default { 16 export default {
13 name: 'RadioGroup', 17 name: 'RadioGroup',
14 mixins: [ Emitter ], 18 mixins: [ Emitter ],
@@ -30,6 +34,10 @@ @@ -30,6 +34,10 @@
30 vertical: { 34 vertical: {
31 type: Boolean, 35 type: Boolean,
32 default: false 36 default: false
  37 + },
  38 + name: {
  39 + type: String,
  40 + default: getUuid
33 } 41 }
34 }, 42 },
35 data () { 43 data () {
@@ -56,12 +64,10 @@ @@ -56,12 +64,10 @@
56 }, 64 },
57 methods: { 65 methods: {
58 updateValue () { 66 updateValue () {
59 - const value = this.value;  
60 this.childrens = findComponentsDownward(this, 'Radio'); 67 this.childrens = findComponentsDownward(this, 'Radio');
61 -  
62 if (this.childrens) { 68 if (this.childrens) {
63 this.childrens.forEach(child => { 69 this.childrens.forEach(child => {
64 - child.currentValue = value == child.label; 70 + child.currentValue = this.value === child.label;
65 child.group = true; 71 child.group = true;
66 }); 72 });
67 } 73 }
@@ -76,6 +82,7 @@ @@ -76,6 +82,7 @@
76 }, 82 },
77 watch: { 83 watch: {
78 value () { 84 value () {
  85 + this.currentValue = this.value;
79 this.updateValue(); 86 this.updateValue();
80 } 87 }
81 } 88 }
src/components/radio/radio.vue
1 <template> 1 <template>
2 - <label  
3 - :class="wrapClasses"  
4 - :tabindex="disabled ? -1 : 0"  
5 - @keyup.space="change"> 2 + <label :class="wrapClasses">
6 <span :class="radioClasses"> 3 <span :class="radioClasses">
7 <span :class="innerClasses"></span> 4 <span :class="innerClasses"></span>
8 <input 5 <input
9 type="radio" 6 type="radio"
10 - tabindex="-1"  
11 :class="inputClasses" 7 :class="inputClasses"
12 :disabled="disabled" 8 :disabled="disabled"
13 :checked="currentValue" 9 :checked="currentValue"
14 - :name="name" 10 + :name="groupName"
15 @change="change" 11 @change="change"
16 - >  
17 - </span><slot>{{ label }}</slot> 12 + @focus="onFocus"
  13 + @blur="onBlur">
  14 + </span>
  15 + <slot>{{ label }}</slot>
18 </label> 16 </label>
19 </template> 17 </template>
20 <script> 18 <script>
@@ -59,7 +57,10 @@ @@ -59,7 +57,10 @@
59 return { 57 return {
60 currentValue: this.value, 58 currentValue: this.value,
61 group: false, 59 group: false,
62 - parent: findComponentUpward(this, 'RadioGroup') 60 + groupName: this.name,
  61 + parent: findComponentUpward(this, 'RadioGroup'),
  62 + focusWrapper: false,
  63 + focusInner: false
63 }; 64 };
64 }, 65 },
65 computed: { 66 computed: {
@@ -70,7 +71,8 @@ @@ -70,7 +71,8 @@
70 [`${prefixCls}-group-item`]: this.group, 71 [`${prefixCls}-group-item`]: this.group,
71 [`${prefixCls}-wrapper-checked`]: this.currentValue, 72 [`${prefixCls}-wrapper-checked`]: this.currentValue,
72 [`${prefixCls}-wrapper-disabled`]: this.disabled, 73 [`${prefixCls}-wrapper-disabled`]: this.disabled,
73 - [`${prefixCls}-${this.size}`]: !!this.size 74 + [`${prefixCls}-${this.size}`]: !!this.size,
  75 + [`${prefixCls}-focus`]: this.focusWrapper
74 } 76 }
75 ]; 77 ];
76 }, 78 },
@@ -84,18 +86,35 @@ @@ -84,18 +86,35 @@
84 ]; 86 ];
85 }, 87 },
86 innerClasses () { 88 innerClasses () {
87 - return `${prefixCls}-inner`; 89 + return [
  90 + `${prefixCls}-inner`,
  91 + {
  92 + [`${prefixCls}-focus`]: this.focusInner
  93 + }
  94 + ];
88 }, 95 },
89 inputClasses () { 96 inputClasses () {
90 return `${prefixCls}-input`; 97 return `${prefixCls}-input`;
91 } 98 }
92 }, 99 },
93 mounted () { 100 mounted () {
94 - if (this.parent) this.group = true;  
95 - if (!this.group) {  
96 - this.updateValue();  
97 - } else { 101 + if (this.parent) {
  102 + this.group = true;
  103 + if (this.name && this.name !== this.parent.name) {
  104 + /* eslint-disable no-console */
  105 + if (console.warn) {
  106 + console.warn('[iview] Name does not match Radio Group name.');
  107 + }
  108 + /* eslint-enable no-console */
  109 + } else {
  110 + this.groupName = this.parent.name;
  111 + }
  112 + }
  113 +
  114 + if (this.group) {
98 this.parent.updateValue(); 115 this.parent.updateValue();
  116 + } else {
  117 + this.updateValue();
99 } 118 }
100 }, 119 },
101 methods: { 120 methods: {
@@ -107,30 +126,43 @@ @@ -107,30 +126,43 @@
107 const checked = event.target.checked; 126 const checked = event.target.checked;
108 this.currentValue = checked; 127 this.currentValue = checked;
109 128
110 - let value = checked ? this.trueValue : this.falseValue; 129 + const value = checked ? this.trueValue : this.falseValue;
111 this.$emit('input', value); 130 this.$emit('input', value);
112 131
113 - if (this.group && this.label !== undefined) {  
114 - this.parent.change({  
115 - value: this.label,  
116 - checked: this.value  
117 - });  
118 - }  
119 - if (!this.group) { 132 + if (this.group) {
  133 + if (this.label !== undefined) {
  134 + this.parent.change({
  135 + value: this.label,
  136 + checked: this.value
  137 + });
  138 + }
  139 + } else {
120 this.$emit('on-change', value); 140 this.$emit('on-change', value);
121 this.dispatch('FormItem', 'on-form-change', value); 141 this.dispatch('FormItem', 'on-form-change', value);
122 } 142 }
123 }, 143 },
124 updateValue () { 144 updateValue () {
125 this.currentValue = this.value === this.trueValue; 145 this.currentValue = this.value === this.trueValue;
  146 + },
  147 + onBlur () {
  148 + this.focusWrapper = false;
  149 + this.focusInner = false;
  150 + },
  151 + onFocus () {
  152 + if (this.group && this.parent.type === 'button') {
  153 + this.focusWrapper = true;
  154 + } else {
  155 + this.focusInner = true;
  156 + }
126 } 157 }
127 }, 158 },
128 watch: { 159 watch: {
129 value (val) { 160 value (val) {
130 - if (val !== this.trueValue && val !== this.falseValue) { 161 + if (val === this.trueValue || val === this.falseValue) {
  162 + this.updateValue();
  163 + } else {
131 throw 'Value should be trueValue or falseValue.'; 164 throw 'Value should be trueValue or falseValue.';
132 } 165 }
133 - this.updateValue();  
134 } 166 }
135 } 167 }
136 }; 168 };
src/styles/components/radio.less
@@ -3,10 +3,16 @@ @@ -3,10 +3,16 @@
3 @radio-inner-prefix-cls: ~"@{radio-prefix-cls}-inner"; 3 @radio-inner-prefix-cls: ~"@{radio-prefix-cls}-inner";
4 @radio-group-button-prefix-cls: ~"@{radio-group-prefix-cls}-button"; 4 @radio-group-button-prefix-cls: ~"@{radio-group-prefix-cls}-button";
5 5
  6 +.@{radio-prefix-cls}-focus {
  7 + box-shadow: 0 0 0 2px fade(@primary-color, 20%);
  8 + z-index: 1;
  9 +}
  10 +
6 .@{radio-group-prefix-cls} { 11 .@{radio-group-prefix-cls} {
7 display: inline-block; 12 display: inline-block;
8 font-size: @font-size-small; 13 font-size: @font-size-small;
9 vertical-align: middle; 14 vertical-align: middle;
  15 + //outline: none;
10 &-vertical{ 16 &-vertical{
11 .@{radio-prefix-cls}-wrapper { 17 .@{radio-prefix-cls}-wrapper {
12 display: block; 18 display: block;
@@ -28,19 +34,14 @@ @@ -28,19 +34,14 @@
28 &-disabled{ 34 &-disabled{
29 cursor: @cursor-disabled; 35 cursor: @cursor-disabled;
30 } 36 }
31 - outline: 0;  
32 - &:focus {  
33 - & .@{radio-inner-prefix-cls} {  
34 - box-shadow: 0 0 0 2px fade(@primary-color, 20%);  
35 - }  
36 - } 37 + //outline: none;
37 } 38 }
38 39
39 .@{radio-prefix-cls} { 40 .@{radio-prefix-cls} {
40 display: inline-block; 41 display: inline-block;
41 margin-right: 4px; 42 margin-right: 4px;
42 white-space: nowrap; 43 white-space: nowrap;
43 - outline: none; 44 + //outline: none;
44 position: relative; 45 position: relative;
45 line-height: 1; 46 line-height: 1;
46 vertical-align: middle; 47 vertical-align: middle;
@@ -177,7 +178,7 @@ span.@{radio-prefix-cls} + * { @@ -177,7 +178,7 @@ span.@{radio-prefix-cls} + * {
177 height: @btn-circle-size; 178 height: @btn-circle-size;
178 line-height: @btn-circle-size - 2px; 179 line-height: @btn-circle-size - 2px;
179 margin: 0; 180 margin: 0;
180 - padding: 0 16px; 181 + padding: 0 16px - 1px;
181 font-size: @font-size-small; 182 font-size: @font-size-small;
182 color: @btn-default-color; 183 color: @btn-default-color;
183 transition: all @transition-time ease-in-out; 184 transition: all @transition-time ease-in-out;
@@ -185,26 +186,37 @@ span.@{radio-prefix-cls} + * { @@ -185,26 +186,37 @@ span.@{radio-prefix-cls} + * {
185 border: 1px solid @border-color-base; 186 border: 1px solid @border-color-base;
186 border-left: 0; 187 border-left: 0;
187 background: #fff; 188 background: #fff;
  189 + position: relative;
188 190
189 > span { 191 > span {
190 margin-left: 0; 192 margin-left: 0;
191 } 193 }
192 194
193 - &:before { 195 + &:before, &:after {
194 content: ''; 196 content: '';
  197 + display: block;
195 position: absolute; 198 position: absolute;
196 width: 1px; 199 width: 1px;
197 height: 100%; 200 height: 100%;
198 left: -1px; 201 left: -1px;
  202 + top: 0;
199 background: @border-color-base; 203 background: @border-color-base;
200 - visibility: hidden; 204 + //visibility: hidden;
201 transition: all @transition-time ease-in-out; 205 transition: all @transition-time ease-in-out;
202 } 206 }
203 207
  208 + &:after{
  209 + height: @btn-circle-size + 4px;
  210 + left: -1px;
  211 + top: -3px;
  212 + background: fade(@primary-color, 20%);
  213 + opacity: 0;
  214 + }
  215 +
204 &:first-child { 216 &:first-child {
205 border-radius: @btn-border-radius 0 0 @btn-border-radius; 217 border-radius: @btn-border-radius 0 0 @btn-border-radius;
206 border-left: 1px solid @border-color-base; 218 border-left: 1px solid @border-color-base;
207 - &:before { 219 + &:before, &:after {
208 display: none; 220 display: none;
209 } 221 }
210 } 222 }
@@ -225,10 +237,6 @@ span.@{radio-prefix-cls} + * { @@ -225,10 +237,6 @@ span.@{radio-prefix-cls} + * {
225 } 237 }
226 } 238 }
227 239
228 - &:focus {  
229 - box-shadow: 0 0 0 2px fade(@primary-color, 20%);  
230 - }  
231 -  
232 .@{radio-prefix-cls}-inner, 240 .@{radio-prefix-cls}-inner,
233 input { 241 input {
234 opacity: 0; 242 opacity: 0;
@@ -241,25 +249,41 @@ span.@{radio-prefix-cls} + * { @@ -241,25 +249,41 @@ span.@{radio-prefix-cls} + * {
241 border-color: @primary-color; 249 border-color: @primary-color;
242 color: @primary-color; 250 color: @primary-color;
243 box-shadow: -1px 0 0 0 @primary-color; 251 box-shadow: -1px 0 0 0 @primary-color;
  252 + z-index: 1;
  253 +
  254 + &:before{
  255 + background: @primary-color;
  256 + opacity: 0.1;
  257 + }
  258 +
  259 + &.@{radio-prefix-cls}-focus{
  260 + box-shadow: -1px 0 0 0 @primary-color, 0 0 0 2px fade(@primary-color, 20%);
  261 + transition: all @transition-time ease-in-out;
  262 + &:after{
  263 + left: -3px;
  264 + top: -3px;
  265 + opacity: 1;
  266 + background: fade(@primary-color, 20%);
  267 + }
  268 + &:first-child{
  269 + box-shadow: 0 0 0 2px fade(@primary-color, 20%);
  270 + }
  271 + }
244 272
245 &:first-child { 273 &:first-child {
246 border-color: @primary-color; 274 border-color: @primary-color;
247 - box-shadow: none!important; 275 + box-shadow: none;
248 } 276 }
249 277
250 &:hover { 278 &:hover {
251 border-color: tint(@primary-color, 20%); 279 border-color: tint(@primary-color, 20%);
252 - box-shadow: -1px 0 0 0 tint(@primary-color, 20%); 280 + //box-shadow: -1px 0 0 0 tint(@primary-color, 20%);
253 color: tint(@primary-color, 20%); 281 color: tint(@primary-color, 20%);
254 } 282 }
255 283
256 - &:focus {  
257 - box-shadow: 0 0 0 2px fade(@primary-color, 20%)!important;  
258 - }  
259 -  
260 &:active { 284 &:active {
261 border-color: shade(@primary-color, 5%); 285 border-color: shade(@primary-color, 5%);
262 - box-shadow: -1px 0 0 0 shade(@primary-color, 5%); 286 + //box-shadow: -1px 0 0 0 shade(@primary-color, 5%);
263 color: shade(@primary-color, 5%); 287 color: shade(@primary-color, 5%);
264 } 288 }
265 } 289 }
@@ -294,6 +318,9 @@ span.@{radio-prefix-cls} + * { @@ -294,6 +318,9 @@ span.@{radio-prefix-cls} + * {
294 height: @btn-circle-size-large; 318 height: @btn-circle-size-large;
295 line-height: @btn-circle-size-large - 2px; 319 line-height: @btn-circle-size-large - 2px;
296 font-size: @font-size-base; 320 font-size: @font-size-base;
  321 + &:after{
  322 + height: @btn-circle-size-large + 4px;
  323 + }
297 } 324 }
298 325
299 .@{radio-group-button-prefix-cls}.@{radio-group-prefix-cls}-small .@{radio-prefix-cls}-wrapper{ 326 .@{radio-group-button-prefix-cls}.@{radio-group-prefix-cls}-small .@{radio-prefix-cls}-wrapper{
@@ -301,6 +328,11 @@ span.@{radio-prefix-cls} + * { @@ -301,6 +328,11 @@ span.@{radio-prefix-cls} + * {
301 line-height: @btn-circle-size-small - 2px; 328 line-height: @btn-circle-size-small - 2px;
302 padding: 0 12px; 329 padding: 0 12px;
303 font-size: @font-size-small; 330 font-size: @font-size-small;
  331 +
  332 + &:after{
  333 + height: @btn-circle-size-small + 4px;
  334 + }
  335 +
304 &:first-child { 336 &:first-child {
305 border-radius: @btn-border-radius-small 0 0 @btn-border-radius-small; 337 border-radius: @btn-border-radius-small 0 0 @btn-border-radius-small;
306 } 338 }