Commit 4aec6a66bbabe979473dbebb9830cea879c1e016
1 parent
47a7f21d
support Select
support Select
Showing
9 changed files
with
343 additions
and
143 deletions
Show diff stats
CHANGE.md
@@ -41,3 +41,5 @@ MenuItem 和 Submenu 的 key 改为了 name | @@ -41,3 +41,5 @@ MenuItem 和 Submenu 的 key 改为了 name | ||
41 | Menu 的 activeKey 改为 activeName,openKeys 改为 openNames | 41 | Menu 的 activeKey 改为 activeName,openKeys 改为 openNames |
42 | ### Cascader | 42 | ### Cascader |
43 | Caspanel 的 sublist 从 prop -> data | 43 | Caspanel 的 sublist 从 prop -> data |
44 | +### Select | ||
45 | +model 改为 value,支持 v-model | ||
44 | \ No newline at end of file | 46 | \ No newline at end of file |
README.md
examples/app.vue
@@ -43,6 +43,7 @@ li + li { border-left: solid 1px #bbb; padding-left: 10px; margin-left: 10px; } | @@ -43,6 +43,7 @@ li + li { border-left: solid 1px #bbb; padding-left: 10px; margin-left: 10px; } | ||
43 | <li><router-link to="/menu">Menu</router-link></li> | 43 | <li><router-link to="/menu">Menu</router-link></li> |
44 | <li><router-link to="/spin">Spin</router-link></li> | 44 | <li><router-link to="/spin">Spin</router-link></li> |
45 | <li><router-link to="/cascader">Cascader</router-link></li> | 45 | <li><router-link to="/cascader">Cascader</router-link></li> |
46 | + <li><router-link to="/select">Select</router-link></li> | ||
46 | </ul> | 47 | </ul> |
47 | </nav> | 48 | </nav> |
48 | <router-view></router-view> | 49 | <router-view></router-view> |
examples/main.js
@@ -136,6 +136,10 @@ const router = new VueRouter({ | @@ -136,6 +136,10 @@ const router = new VueRouter({ | ||
136 | { | 136 | { |
137 | path: '/cascader', | 137 | path: '/cascader', |
138 | component: require('./routers/cascader.vue') | 138 | component: require('./routers/cascader.vue') |
139 | + }, | ||
140 | + { | ||
141 | + path: '/select', | ||
142 | + component: require('./routers/select.vue') | ||
139 | } | 143 | } |
140 | ] | 144 | ] |
141 | }); | 145 | }); |
examples/routers/select.vue
1 | +<!--<template>--> | ||
2 | + <!--<div>--> | ||
3 | + <!--<i-select v-model="model1" style="width:200px" clearable>--> | ||
4 | + <!--<i-option v-for="item in cityList" :value="item.value">{{ item.label }}</i-option>--> | ||
5 | + <!--</i-select>--> | ||
6 | + <!--{{ model1 }}--> | ||
7 | + <!--<div @click="c">change</div>--> | ||
8 | + <!--</div>--> | ||
9 | +<!--</template>--> | ||
10 | +<!--<script>--> | ||
11 | + <!--export default {--> | ||
12 | + <!--data () {--> | ||
13 | + <!--return {--> | ||
14 | + <!--cityList: [--> | ||
15 | + <!--{--> | ||
16 | + <!--value: 'beijing',--> | ||
17 | + <!--label: '北京市'--> | ||
18 | + <!--},--> | ||
19 | + <!--{--> | ||
20 | + <!--value: 'shanghai',--> | ||
21 | + <!--label: '上海市'--> | ||
22 | + <!--},--> | ||
23 | + <!--{--> | ||
24 | + <!--value: 'shenzhen',--> | ||
25 | + <!--label: '深圳市'--> | ||
26 | + <!--},--> | ||
27 | + <!--{--> | ||
28 | + <!--value: 'hangzhou',--> | ||
29 | + <!--label: '杭州市'--> | ||
30 | + <!--},--> | ||
31 | + <!--{--> | ||
32 | + <!--value: 'nanjing',--> | ||
33 | + <!--label: '南京市'--> | ||
34 | + <!--},--> | ||
35 | + <!--{--> | ||
36 | + <!--value: 'chongqing',--> | ||
37 | + <!--label: '重庆市'--> | ||
38 | + <!--}--> | ||
39 | + <!--],--> | ||
40 | + <!--model1: ''--> | ||
41 | + <!--}--> | ||
42 | + <!--},--> | ||
43 | + <!--methods: {--> | ||
44 | + <!--c () {--> | ||
45 | + <!--this.model1 = 'hangzhou'--> | ||
46 | + <!--}--> | ||
47 | + <!--}--> | ||
48 | + <!--}--> | ||
49 | +<!--</script>--> | ||
50 | + | ||
51 | + | ||
52 | +<!--<template>--> | ||
53 | + <!--<div>--> | ||
54 | + <!--<i-select v-model="model5" disabled style="width:200px">--> | ||
55 | + <!--<i-option v-for="item in cityList" :value="item.value">{{ item.label }}</i-option>--> | ||
56 | + <!--</i-select>--> | ||
57 | + <!--<i-select v-model="model6" style="width:200px">--> | ||
58 | + <!--<i-option value="beijing">北京市</i-option>--> | ||
59 | + <!--<i-option value="shanghai" disabled>上海市</i-option>--> | ||
60 | + <!--<i-option value="shenzhen">深圳市</i-option>--> | ||
61 | + <!--</i-select>--> | ||
62 | + <!--</div>--> | ||
63 | +<!--</template>--> | ||
64 | +<!--<script>--> | ||
65 | + <!--export default {--> | ||
66 | + <!--data () {--> | ||
67 | + <!--return {--> | ||
68 | + <!--cityList: [--> | ||
69 | + <!--{--> | ||
70 | + <!--value: 'beijing',--> | ||
71 | + <!--label: '北京市'--> | ||
72 | + <!--},--> | ||
73 | + <!--{--> | ||
74 | + <!--value: 'shanghai',--> | ||
75 | + <!--label: '上海市'--> | ||
76 | + <!--},--> | ||
77 | + <!--{--> | ||
78 | + <!--value: 'shenzhen',--> | ||
79 | + <!--label: '深圳市'--> | ||
80 | + <!--},--> | ||
81 | + <!--{--> | ||
82 | + <!--value: 'hangzhou',--> | ||
83 | + <!--label: '杭州市'--> | ||
84 | + <!--},--> | ||
85 | + <!--{--> | ||
86 | + <!--value: 'nanjing',--> | ||
87 | + <!--label: '南京市'--> | ||
88 | + <!--},--> | ||
89 | + <!--{--> | ||
90 | + <!--value: 'chongqing',--> | ||
91 | + <!--label: '重庆市'--> | ||
92 | + <!--}--> | ||
93 | + <!--],--> | ||
94 | + <!--model5: '',--> | ||
95 | + <!--model6: ''--> | ||
96 | + <!--}--> | ||
97 | + <!--}--> | ||
98 | + <!--}--> | ||
99 | +<!--</script>--> | ||
100 | + | ||
101 | + | ||
102 | + | ||
103 | +<!--<template>--> | ||
104 | + <!--<div>--> | ||
105 | + <!--<i-select v-model="model7" style="width:200px">--> | ||
106 | + <!--<Option-group label="热门城市">--> | ||
107 | + <!--<i-option v-for="item in cityList" :value="item.value">{{ item.label }}</i-option>--> | ||
108 | + <!--</Option-group>--> | ||
109 | + <!--<Option-group label="其它城市">--> | ||
110 | + <!--<i-option v-for="item in cityList" :value="item.value">{{ item.label }}</i-option>--> | ||
111 | + <!--</Option-group>--> | ||
112 | + <!--</i-select>--> | ||
113 | + <!--</div>--> | ||
114 | +<!--</template>--> | ||
115 | +<!--<script>--> | ||
116 | + <!--export default {--> | ||
117 | + <!--data () {--> | ||
118 | + <!--return {--> | ||
119 | + <!--cityList: [--> | ||
120 | + <!--{--> | ||
121 | + <!--value: 'beijing',--> | ||
122 | + <!--label: '北京市'--> | ||
123 | + <!--},--> | ||
124 | + <!--{--> | ||
125 | + <!--value: 'shanghai',--> | ||
126 | + <!--label: '上海市'--> | ||
127 | + <!--},--> | ||
128 | + <!--{--> | ||
129 | + <!--value: 'shenzhen',--> | ||
130 | + <!--label: '深圳市'--> | ||
131 | + <!--},--> | ||
132 | + <!--{--> | ||
133 | + <!--value: 'hangzhou',--> | ||
134 | + <!--label: '杭州市'--> | ||
135 | + <!--},--> | ||
136 | + <!--{--> | ||
137 | + <!--value: 'nanjing',--> | ||
138 | + <!--label: '南京市'--> | ||
139 | + <!--},--> | ||
140 | + <!--{--> | ||
141 | + <!--value: 'chongqing',--> | ||
142 | + <!--label: '重庆市'--> | ||
143 | + <!--}--> | ||
144 | + <!--],--> | ||
145 | + <!--model7: ''--> | ||
146 | + <!--}--> | ||
147 | + <!--}--> | ||
148 | + <!--}--> | ||
149 | +<!--</script>--> | ||
150 | + | ||
151 | +<!--<template>--> | ||
152 | + <!--<div>--> | ||
153 | + <!--<i-select v-model="model10" multiple style="width:260px">--> | ||
154 | + <!--<i-option v-for="item in cityList" :value="item.value">{{ item.label }}</i-option>--> | ||
155 | + <!--</i-select>--> | ||
156 | + <!--</div>--> | ||
157 | +<!--</template>--> | ||
158 | +<!--<script>--> | ||
159 | + <!--export default {--> | ||
160 | + <!--data () {--> | ||
161 | + <!--return {--> | ||
162 | + <!--cityList: [--> | ||
163 | + <!--{--> | ||
164 | + <!--value: 'beijing',--> | ||
165 | + <!--label: '北京市'--> | ||
166 | + <!--},--> | ||
167 | + <!--{--> | ||
168 | + <!--value: 'shanghai',--> | ||
169 | + <!--label: '上海市'--> | ||
170 | + <!--},--> | ||
171 | + <!--{--> | ||
172 | + <!--value: 'shenzhen',--> | ||
173 | + <!--label: '深圳市'--> | ||
174 | + <!--},--> | ||
175 | + <!--{--> | ||
176 | + <!--value: 'hangzhou',--> | ||
177 | + <!--label: '杭州市'--> | ||
178 | + <!--},--> | ||
179 | + <!--{--> | ||
180 | + <!--value: 'nanjing',--> | ||
181 | + <!--label: '南京市'--> | ||
182 | + <!--},--> | ||
183 | + <!--{--> | ||
184 | + <!--value: 'chongqing',--> | ||
185 | + <!--label: '重庆市'--> | ||
186 | + <!--}--> | ||
187 | + <!--],--> | ||
188 | + <!--model10: []--> | ||
189 | + <!--}--> | ||
190 | + <!--}--> | ||
191 | + <!--}--> | ||
192 | +<!--</script>--> | ||
193 | + | ||
1 | <template> | 194 | <template> |
2 | - <Row> | ||
3 | - <i-col span="12" style="padding-right:10px"> | ||
4 | - <i-select :model.sync="model111" filterable> | ||
5 | - <i-option v-for="item in cityList1" :value="item.value">{{ item.label }}</i-option> | ||
6 | - </i-select> | ||
7 | - </i-col> | ||
8 | - </Row> | ||
9 | - <Row> | ||
10 | - <i-col span="12" style="padding-right:10px"> | ||
11 | - <i-select :model.sync="model112" filterable> | ||
12 | - <i-option v-for="item in cityList2" :value="item.value">{{ item.label }}</i-option> | ||
13 | - </i-select> | ||
14 | - </i-col> | ||
15 | - </Row> | ||
16 | - <Row> | ||
17 | - <i-col span="12"> | ||
18 | - <i-select :model.sync="model12" filterable multiple> | ||
19 | - <i-option v-for="item in cityList1" :value="item.value">{{ item.label }}</i-option> | ||
20 | - </i-select> | ||
21 | - </i-col> | ||
22 | - </Row> | 195 | + <div> |
196 | + <Row> | ||
197 | + <i-col span="12" style="padding-right:10px"> | ||
198 | + <i-select v-model="model11" filterable> | ||
199 | + <i-option v-for="item in cityList" :value="item.value">{{ item.label }}</i-option> | ||
200 | + </i-select> | ||
201 | + </i-col> | ||
202 | + <i-col span="12"> | ||
203 | + <i-select v-model="model12" filterable multiple> | ||
204 | + <i-option v-for="item in cityList" :value="item.value">{{ item.label }}</i-option> | ||
205 | + </i-select> | ||
206 | + </i-col> | ||
207 | + </Row> | ||
208 | + <div @click="model11 = 'shanghai'">change</div> | ||
209 | + </div> | ||
23 | </template> | 210 | </template> |
24 | <script> | 211 | <script> |
25 | -const cityList = [ | ||
26 | - { | ||
27 | - value: 'beijing', | ||
28 | - label: '北京市' | ||
29 | - }, | ||
30 | - { | ||
31 | - value: 'shanghai', | ||
32 | - label: '上海市' | ||
33 | - }, | ||
34 | - { | ||
35 | - value: 'shenzhen', | ||
36 | - label: '深圳市' | ||
37 | - }, | ||
38 | - { | ||
39 | - value: 'hangzhou', | ||
40 | - label: '杭州市' | ||
41 | - }, | ||
42 | - { | ||
43 | - value: 'nanjing', | ||
44 | - label: '南京市' | ||
45 | - }, | ||
46 | - { | ||
47 | - value: 'chongqing', | ||
48 | - label: '重庆市' | ||
49 | - } | ||
50 | -] | ||
51 | export default { | 212 | export default { |
52 | data () { | 213 | data () { |
53 | return { | 214 | return { |
54 | - cityList1: cityList, | ||
55 | - model111: '', | ||
56 | - | ||
57 | - cityList2: [], | ||
58 | - model112: 'beijing', | ||
59 | - | 215 | + cityList: [ |
216 | + { | ||
217 | + value: 'beijing', | ||
218 | + label: '北京市' | ||
219 | + }, | ||
220 | + { | ||
221 | + value: 'shanghai', | ||
222 | + label: '上海市' | ||
223 | + }, | ||
224 | + { | ||
225 | + value: 'shenzhen', | ||
226 | + label: '深圳市' | ||
227 | + }, | ||
228 | + { | ||
229 | + value: 'hangzhou', | ||
230 | + label: '杭州市' | ||
231 | + }, | ||
232 | + { | ||
233 | + value: 'nanjing', | ||
234 | + label: '南京市' | ||
235 | + }, | ||
236 | + { | ||
237 | + value: 'chongqing', | ||
238 | + label: '重庆市' | ||
239 | + } | ||
240 | + ], | ||
241 | + model11: '', | ||
60 | model12: [] | 242 | model12: [] |
61 | } | 243 | } |
62 | - }, | ||
63 | - ready() { | ||
64 | - this.model111 = 'hangzhou' | ||
65 | - setTimeout(()=>{ | ||
66 | - this.cityList2 = cityList | ||
67 | - }, 500) | ||
68 | } | 244 | } |
69 | } | 245 | } |
70 | </script> | 246 | </script> |
src/components/select/option-group.vue
@@ -2,7 +2,7 @@ | @@ -2,7 +2,7 @@ | ||
2 | <li :class="[prefixCls + '-wrap']" v-show="!hidden"> | 2 | <li :class="[prefixCls + '-wrap']" v-show="!hidden"> |
3 | <div :class="[prefixCls + '-title']">{{ label }}</div> | 3 | <div :class="[prefixCls + '-title']">{{ label }}</div> |
4 | <ul> | 4 | <ul> |
5 | - <li :class="[prefixCls]" v-el:options><slot></slot></li> | 5 | + <li :class="[prefixCls]" ref="options"><slot></slot></li> |
6 | </ul> | 6 | </ul> |
7 | </li> | 7 | </li> |
8 | </template> | 8 | </template> |
@@ -10,6 +10,7 @@ | @@ -10,6 +10,7 @@ | ||
10 | const prefixCls = 'ivu-select-group'; | 10 | const prefixCls = 'ivu-select-group'; |
11 | 11 | ||
12 | export default { | 12 | export default { |
13 | + name: 'OptionGroup', | ||
13 | props: { | 14 | props: { |
14 | label: { | 15 | label: { |
15 | type: String, | 16 | type: String, |
@@ -25,7 +26,7 @@ | @@ -25,7 +26,7 @@ | ||
25 | methods: { | 26 | methods: { |
26 | queryChange () { | 27 | queryChange () { |
27 | this.$nextTick(() => { | 28 | this.$nextTick(() => { |
28 | - const options = this.$els.options.querySelectorAll('.ivu-select-item'); | 29 | + const options = this.$refs.options.querySelectorAll('.ivu-select-item'); |
29 | let hasVisibleOption = false; | 30 | let hasVisibleOption = false; |
30 | for (let i = 0; i < options.length; i++) { | 31 | for (let i = 0; i < options.length; i++) { |
31 | if (options[i].style.display !== 'none') { | 32 | if (options[i].style.display !== 'none') { |
@@ -37,11 +38,11 @@ | @@ -37,11 +38,11 @@ | ||
37 | }); | 38 | }); |
38 | } | 39 | } |
39 | }, | 40 | }, |
40 | - events: { | ||
41 | - 'on-query-change' () { | 41 | + mounted () { |
42 | + this.$on('on-query-change', () => { | ||
42 | this.queryChange(); | 43 | this.queryChange(); |
43 | return true; | 44 | return true; |
44 | - } | 45 | + }); |
45 | } | 46 | } |
46 | }; | 47 | }; |
47 | </script> | 48 | </script> |
src/components/select/option.vue
@@ -2,9 +2,14 @@ | @@ -2,9 +2,14 @@ | ||
2 | <li :class="classes" @click.stop="select" @mouseout.stop="blur" v-show="!hidden"><slot>{{ showLabel }}</slot></li> | 2 | <li :class="classes" @click.stop="select" @mouseout.stop="blur" v-show="!hidden"><slot>{{ showLabel }}</slot></li> |
3 | </template> | 3 | </template> |
4 | <script> | 4 | <script> |
5 | + import Emitter from '../../mixins/emitter'; | ||
6 | + | ||
5 | const prefixCls = 'ivu-select-item'; | 7 | const prefixCls = 'ivu-select-item'; |
6 | 8 | ||
7 | export default { | 9 | export default { |
10 | + name: 'iOption', | ||
11 | + componentName: 'select-item', | ||
12 | + mixins: [ Emitter ], | ||
8 | props: { | 13 | props: { |
9 | value: { | 14 | value: { |
10 | type: [String, Number], | 15 | type: [String, Number], |
@@ -18,7 +23,6 @@ | @@ -18,7 +23,6 @@ | ||
18 | default: false | 23 | default: false |
19 | } | 24 | } |
20 | }, | 25 | }, |
21 | - componentName: 'select-item', | ||
22 | data () { | 26 | data () { |
23 | return { | 27 | return { |
24 | selected: false, | 28 | selected: false, |
@@ -49,7 +53,7 @@ | @@ -49,7 +53,7 @@ | ||
49 | return false; | 53 | return false; |
50 | } | 54 | } |
51 | 55 | ||
52 | - this.$dispatch('on-select-selected', this.value); | 56 | + this.dispatch('iSelect', 'on-select-selected', this.value); |
53 | }, | 57 | }, |
54 | blur () { | 58 | blur () { |
55 | this.isFocus = false; | 59 | this.isFocus = false; |
@@ -59,16 +63,14 @@ | @@ -59,16 +63,14 @@ | ||
59 | this.hidden = !new RegExp(parsedQuery, 'i').test(this.searchLabel); | 63 | this.hidden = !new RegExp(parsedQuery, 'i').test(this.searchLabel); |
60 | } | 64 | } |
61 | }, | 65 | }, |
62 | - compiled () { | 66 | + mounted () { |
63 | this.searchLabel = this.$el.innerHTML; | 67 | this.searchLabel = this.$el.innerHTML; |
64 | - }, | ||
65 | - events: { | ||
66 | - 'on-select-close' () { | 68 | + this.$on('on-select-close', () => { |
67 | this.isFocus = false; | 69 | this.isFocus = false; |
68 | - }, | ||
69 | - 'on-query-change' (val) { | 70 | + }); |
71 | + this.$on('on-query-change', (val) => { | ||
70 | this.queryChange(val); | 72 | this.queryChange(val); |
71 | - } | 73 | + }); |
72 | } | 74 | } |
73 | }; | 75 | }; |
74 | </script> | 76 | </script> |
src/components/select/select.vue
@@ -2,11 +2,11 @@ | @@ -2,11 +2,11 @@ | ||
2 | <div :class="classes" v-clickoutside="handleClose"> | 2 | <div :class="classes" v-clickoutside="handleClose"> |
3 | <div | 3 | <div |
4 | :class="[prefixCls + '-selection']" | 4 | :class="[prefixCls + '-selection']" |
5 | - v-el:reference | 5 | + ref="reference" |
6 | @click="toggleMenu"> | 6 | @click="toggleMenu"> |
7 | - <div class="ivu-tag" v-for="item in selectedMultiple"> | 7 | + <div class="ivu-tag" v-for="(item, index) in selectedMultiple"> |
8 | <span class="ivu-tag-text">{{ item.label }}</span> | 8 | <span class="ivu-tag-text">{{ item.label }}</span> |
9 | - <Icon type="ios-close-empty" @click.stop="removeTag($index)"></Icon> | 9 | + <Icon type="ios-close-empty" @click.native.stop="removeTag(index)"></Icon> |
10 | </div> | 10 | </div> |
11 | <span :class="[prefixCls + '-placeholder']" v-show="showPlaceholder && !filterable">{{ placeholder }}</span> | 11 | <span :class="[prefixCls + '-placeholder']" v-show="showPlaceholder && !filterable">{{ placeholder }}</span> |
12 | <span :class="[prefixCls + '-selected-value']" v-show="!showPlaceholder && !multiple && !filterable">{{ selectedSingle }}</span> | 12 | <span :class="[prefixCls + '-selected-value']" v-show="!showPlaceholder && !multiple && !filterable">{{ selectedSingle }}</span> |
@@ -20,31 +20,35 @@ | @@ -20,31 +20,35 @@ | ||
20 | @blur="handleBlur" | 20 | @blur="handleBlur" |
21 | @keydown="resetInputState" | 21 | @keydown="resetInputState" |
22 | @keydown.delete="handleInputDelete" | 22 | @keydown.delete="handleInputDelete" |
23 | - v-el:input> | ||
24 | - <Icon type="ios-close" :class="[prefixCls + '-arrow']" v-show="showCloseIcon" @click.stop="clearSingleSelect"></Icon> | 23 | + ref="input"> |
24 | + <Icon type="ios-close" :class="[prefixCls + '-arrow']" v-show="showCloseIcon" @click.native.stop="clearSingleSelect"></Icon> | ||
25 | <Icon type="arrow-down-b" :class="[prefixCls + '-arrow']"></Icon> | 25 | <Icon type="arrow-down-b" :class="[prefixCls + '-arrow']"></Icon> |
26 | </div> | 26 | </div> |
27 | - <Dropdown v-show="visible" transition="slide-up" v-ref:dropdown> | ||
28 | - <ul v-show="notFound" :class="[prefixCls + '-not-found']"><li>{{ notFoundText }}</li></ul> | ||
29 | - <ul v-else :class="[prefixCls + '-dropdown-list']" v-el:options><slot></slot></ul> | ||
30 | - </Dropdown> | 27 | + <transition name="slide-up"> |
28 | + <Drop v-show="visible" ref="dropdown"> | ||
29 | + <ul v-show="notFound" :class="[prefixCls + '-not-found']"><li>{{ notFoundText }}</li></ul> | ||
30 | + <ul v-show="!notFound" :class="[prefixCls + '-dropdown-list']" ref="options"><slot></slot></ul> | ||
31 | + </Drop> | ||
32 | + </transition> | ||
31 | </div> | 33 | </div> |
32 | </template> | 34 | </template> |
33 | <script> | 35 | <script> |
34 | import Icon from '../icon'; | 36 | import Icon from '../icon'; |
35 | - import Dropdown from './dropdown.vue'; | 37 | + import Drop from './dropdown.vue'; |
36 | import clickoutside from '../../directives/clickoutside'; | 38 | import clickoutside from '../../directives/clickoutside'; |
37 | import { oneOf, MutationObserver } from '../../utils/assist'; | 39 | import { oneOf, MutationObserver } from '../../utils/assist'; |
38 | import { t } from '../../locale'; | 40 | import { t } from '../../locale'; |
41 | + import Emitter from '../../mixins/emitter'; | ||
39 | 42 | ||
40 | const prefixCls = 'ivu-select'; | 43 | const prefixCls = 'ivu-select'; |
41 | 44 | ||
42 | export default { | 45 | export default { |
43 | name: 'iSelect', | 46 | name: 'iSelect', |
44 | - components: { Icon, Dropdown }, | 47 | + mixins: [ Emitter ], |
48 | + components: { Icon, Drop }, | ||
45 | directives: { clickoutside }, | 49 | directives: { clickoutside }, |
46 | props: { | 50 | props: { |
47 | - model: { | 51 | + value: { |
48 | type: [String, Number, Array], | 52 | type: [String, Number, Array], |
49 | default: '' | 53 | default: '' |
50 | }, | 54 | }, |
@@ -101,7 +105,8 @@ | @@ -101,7 +105,8 @@ | ||
101 | query: '', | 105 | query: '', |
102 | inputLength: 20, | 106 | inputLength: 20, |
103 | notFound: false, | 107 | notFound: false, |
104 | - slotChangeDuration: false // if slot change duration and in multiple, set true and after slot change, set false | 108 | + slotChangeDuration: false, // if slot change duration and in multiple, set true and after slot change, set false |
109 | + model: this.value | ||
105 | }; | 110 | }; |
106 | }, | 111 | }, |
107 | computed: { | 112 | computed: { |
@@ -161,7 +166,7 @@ | @@ -161,7 +166,7 @@ | ||
161 | hideMenu () { | 166 | hideMenu () { |
162 | this.visible = false; | 167 | this.visible = false; |
163 | this.focusIndex = 0; | 168 | this.focusIndex = 0; |
164 | - this.$broadcast('on-select-close'); | 169 | + this.broadcast('iOption', 'on-select-close'); |
165 | }, | 170 | }, |
166 | // find option component | 171 | // find option component |
167 | findChild (cb) { | 172 | findChild (cb) { |
@@ -289,10 +294,10 @@ | @@ -289,10 +294,10 @@ | ||
289 | this.model.splice(index, 1); | 294 | this.model.splice(index, 1); |
290 | 295 | ||
291 | if (this.filterable && this.visible) { | 296 | if (this.filterable && this.visible) { |
292 | - this.$els.input.focus(); | 297 | + this.$refs.input.focus(); |
293 | } | 298 | } |
294 | 299 | ||
295 | - this.$broadcast('on-update-popper'); | 300 | + this.broadcast('Drop', 'on-update-popper'); |
296 | }, | 301 | }, |
297 | // to select option for single | 302 | // to select option for single |
298 | toggleSingleSelected (value, init = false) { | 303 | toggleSingleSelected (value, init = false) { |
@@ -316,13 +321,15 @@ | @@ -316,13 +321,15 @@ | ||
316 | value: value, | 321 | value: value, |
317 | label: label | 322 | label: label |
318 | }); | 323 | }); |
319 | - this.$dispatch('on-form-change', { | ||
320 | - value: value, | ||
321 | - label: label | ||
322 | - }); | 324 | + // todo 事件 |
325 | +// this.$dispatch('on-form-change', { | ||
326 | +// value: value, | ||
327 | +// label: label | ||
328 | +// }); | ||
323 | } else { | 329 | } else { |
324 | this.$emit('on-change', value); | 330 | this.$emit('on-change', value); |
325 | - this.$dispatch('on-form-change', value); | 331 | + // todo 事件 |
332 | +// this.$dispatch('on-form-change', value); | ||
326 | } | 333 | } |
327 | } | 334 | } |
328 | } | 335 | } |
@@ -351,10 +358,12 @@ | @@ -351,10 +358,12 @@ | ||
351 | if (!init) { | 358 | if (!init) { |
352 | if (this.labelInValue) { | 359 | if (this.labelInValue) { |
353 | this.$emit('on-change', hybridValue); | 360 | this.$emit('on-change', hybridValue); |
354 | - this.$dispatch('on-form-change', hybridValue); | ||
355 | - } else { | 361 | + // todo 事件 |
362 | +// this.$dispatch('on-form-change', hybridValue); | ||
363 | +// } else { | ||
356 | this.$emit('on-change', value); | 364 | this.$emit('on-change', value); |
357 | - this.$dispatch('on-form-change', value); | 365 | + // todo 事件 |
366 | +// this.$dispatch('on-form-change', value); | ||
358 | } | 367 | } |
359 | } | 368 | } |
360 | } | 369 | } |
@@ -463,7 +472,7 @@ | @@ -463,7 +472,7 @@ | ||
463 | }, 300); | 472 | }, 300); |
464 | }, | 473 | }, |
465 | resetInputState () { | 474 | resetInputState () { |
466 | - this.inputLength = this.$els.input.value.length * 12 + 20; | 475 | + this.inputLength = this.$refs.input.value.length * 12 + 20; |
467 | }, | 476 | }, |
468 | handleInputDelete () { | 477 | handleInputDelete () { |
469 | if (this.multiple && this.model.length && this.query === '') { | 478 | if (this.multiple && this.model.length && this.query === '') { |
@@ -495,7 +504,7 @@ | @@ -495,7 +504,7 @@ | ||
495 | } | 504 | } |
496 | } | 505 | } |
497 | }, | 506 | }, |
498 | - compiled () { | 507 | + mounted () { |
499 | this.modelToQuery(); | 508 | this.modelToQuery(); |
500 | 509 | ||
501 | this.updateOptions(true); | 510 | this.updateOptions(true); |
@@ -509,13 +518,44 @@ | @@ -509,13 +518,44 @@ | ||
509 | this.updateOptions(true, true); | 518 | this.updateOptions(true, true); |
510 | }); | 519 | }); |
511 | 520 | ||
512 | - this.observer.observe(this.$els.options, { | 521 | + this.observer.observe(this.$refs.options, { |
513 | // attributes: true, | 522 | // attributes: true, |
514 | childList: true, | 523 | childList: true, |
515 | characterData: true, | 524 | characterData: true, |
516 | subtree: true | 525 | subtree: true |
517 | }); | 526 | }); |
518 | } | 527 | } |
528 | + | ||
529 | + this.$on('on-select-selected', (value) => { | ||
530 | + if (this.model === value) { | ||
531 | + this.hideMenu(); | ||
532 | + } else { | ||
533 | + if (this.multiple) { | ||
534 | + const index = this.model.indexOf(value); | ||
535 | + if (index >= 0) { | ||
536 | + this.removeTag(index); | ||
537 | + } else { | ||
538 | + this.model.push(value); | ||
539 | + this.broadcast('Drop', 'on-update-popper'); | ||
540 | + } | ||
541 | + | ||
542 | + if (this.filterable) { | ||
543 | + this.query = ''; | ||
544 | + this.$refs.input.focus(); | ||
545 | + } | ||
546 | + } else { | ||
547 | + this.model = value; | ||
548 | + | ||
549 | + if (this.filterable) { | ||
550 | + this.findChild((child) => { | ||
551 | + if (child.value === value) { | ||
552 | + this.query = child.label === undefined ? child.searchLabel : child.label; | ||
553 | + } | ||
554 | + }); | ||
555 | + } | ||
556 | + } | ||
557 | + } | ||
558 | + }); | ||
519 | }, | 559 | }, |
520 | beforeDestroy () { | 560 | beforeDestroy () { |
521 | document.removeEventListener('keydown', this.handleKeydown); | 561 | document.removeEventListener('keydown', this.handleKeydown); |
@@ -524,7 +564,11 @@ | @@ -524,7 +564,11 @@ | ||
524 | } | 564 | } |
525 | }, | 565 | }, |
526 | watch: { | 566 | watch: { |
567 | + value (val) { | ||
568 | + this.model = val; | ||
569 | + }, | ||
527 | model () { | 570 | model () { |
571 | + this.$emit('input', this.model); | ||
528 | this.modelToQuery(); | 572 | this.modelToQuery(); |
529 | if (this.multiple) { | 573 | if (this.multiple) { |
530 | if (this.slotChangeDuration) { | 574 | if (this.slotChangeDuration) { |
@@ -539,18 +583,20 @@ | @@ -539,18 +583,20 @@ | ||
539 | visible (val) { | 583 | visible (val) { |
540 | if (val) { | 584 | if (val) { |
541 | if (this.multiple && this.filterable) { | 585 | if (this.multiple && this.filterable) { |
542 | - this.$els.input.focus(); | 586 | + this.$refs.input.focus(); |
543 | } | 587 | } |
544 | - this.$broadcast('on-update-popper'); | 588 | + this.broadcast('Drop', 'on-update-popper'); |
545 | } else { | 589 | } else { |
546 | if (this.filterable) { | 590 | if (this.filterable) { |
547 | - this.$els.input.blur(); | 591 | + this.$refs.input.blur(); |
548 | } | 592 | } |
549 | - this.$broadcast('on-destroy-popper'); | 593 | + this.broadcast('Drop', 'on-destroy-popper'); |
550 | } | 594 | } |
551 | }, | 595 | }, |
552 | query (val) { | 596 | query (val) { |
553 | - this.$broadcast('on-query-change', val); | 597 | + // todo 这里会重复 |
598 | + this.broadcast('OptionGroup', 'on-query-change', val); | ||
599 | + this.broadcast('iOption', 'on-query-change', val); | ||
554 | let is_hidden = true; | 600 | let is_hidden = true; |
555 | 601 | ||
556 | this.$nextTick(() => { | 602 | this.$nextTick(() => { |
@@ -561,39 +607,7 @@ | @@ -561,39 +607,7 @@ | ||
561 | }); | 607 | }); |
562 | this.notFound = is_hidden; | 608 | this.notFound = is_hidden; |
563 | }); | 609 | }); |
564 | - this.$broadcast('on-update-popper'); | ||
565 | - } | ||
566 | - }, | ||
567 | - events: { | ||
568 | - 'on-select-selected' (value) { | ||
569 | - if (this.model === value) { | ||
570 | - this.hideMenu(); | ||
571 | - } else { | ||
572 | - if (this.multiple) { | ||
573 | - const index = this.model.indexOf(value); | ||
574 | - if (index >= 0) { | ||
575 | - this.removeTag(index); | ||
576 | - } else { | ||
577 | - this.model.push(value); | ||
578 | - this.$broadcast('on-update-popper'); | ||
579 | - } | ||
580 | - | ||
581 | - if (this.filterable) { | ||
582 | - this.query = ''; | ||
583 | - this.$els.input.focus(); | ||
584 | - } | ||
585 | - } else { | ||
586 | - this.model = value; | ||
587 | - | ||
588 | - if (this.filterable) { | ||
589 | - this.findChild((child) => { | ||
590 | - if (child.value === value) { | ||
591 | - this.query = child.label === undefined ? child.searchLabel : child.label; | ||
592 | - } | ||
593 | - }); | ||
594 | - } | ||
595 | - } | ||
596 | - } | 610 | + this.broadcast('Drop', 'on-update-popper'); |
597 | } | 611 | } |
598 | } | 612 | } |
599 | }; | 613 | }; |
src/index.js
@@ -43,7 +43,7 @@ import Tooltip from './components/tooltip'; | @@ -43,7 +43,7 @@ import Tooltip from './components/tooltip'; | ||
43 | import Tree from './components/tree'; | 43 | import Tree from './components/tree'; |
44 | import Upload from './components/upload'; | 44 | import Upload from './components/upload'; |
45 | import { Row, Col } from './components/grid'; | 45 | import { Row, Col } from './components/grid'; |
46 | -// import { Select, Option, OptionGroup } from './components/select'; | 46 | +import { Select, Option, OptionGroup } from './components/select'; |
47 | import locale from './locale'; | 47 | import locale from './locale'; |
48 | 48 | ||
49 | const iview = { | 49 | const iview = { |
@@ -83,8 +83,8 @@ const iview = { | @@ -83,8 +83,8 @@ const iview = { | ||
83 | // Message, | 83 | // Message, |
84 | // Modal, | 84 | // Modal, |
85 | // Notice, | 85 | // Notice, |
86 | - // iOption: Option, | ||
87 | - // OptionGroup, | 86 | + iOption: Option, |
87 | + OptionGroup, | ||
88 | // Page, | 88 | // Page, |
89 | Panel: Collapse.Panel, | 89 | Panel: Collapse.Panel, |
90 | Poptip, | 90 | Poptip, |
@@ -93,7 +93,7 @@ const iview = { | @@ -93,7 +93,7 @@ const iview = { | ||
93 | RadioGroup: Radio.Group, | 93 | RadioGroup: Radio.Group, |
94 | Rate, | 94 | Rate, |
95 | Row, | 95 | Row, |
96 | - // iSelect: Select, | 96 | + iSelect: Select, |
97 | Slider, | 97 | Slider, |
98 | Spin, | 98 | Spin, |
99 | Step: Steps.Step, | 99 | Step: Steps.Step, |