Commit fc7ef072167e0e8598c51b2fa1203def11606281
1 parent
d47ea998
support Input
support Input
Showing
6 changed files
with
62 additions
and
152 deletions
Show diff stats
README.md
src/components/input/input.vue
1 | <template> | 1 | <template> |
2 | <div :class="wrapClasses"> | 2 | <div :class="wrapClasses"> |
3 | <template v-if="type !== 'textarea'"> | 3 | <template v-if="type !== 'textarea'"> |
4 | - <div :class="[prefixCls + '-group-prepend']" v-if="prepend" v-show="slotReady" v-el:prepend><slot name="prepend"></slot></div> | 4 | + <div :class="[prefixCls + '-group-prepend']" v-if="prepend" v-show="slotReady" ref="prepend"><slot name="prepend"></slot></div> |
5 | <i class="ivu-icon" :class="['ivu-icon-' + icon, prefixCls + '-icon']" v-if="icon" @click="handleIconClick"></i> | 5 | <i class="ivu-icon" :class="['ivu-icon-' + icon, prefixCls + '-icon']" v-if="icon" @click="handleIconClick"></i> |
6 | - <i class="ivu-icon ivu-icon-load-c ivu-load-loop" :class="[prefixCls + '-icon', prefixCls + '-icon-validate']" v-else transition="fade"></i> | 6 | + <transition name="fade"> |
7 | + <i class="ivu-icon ivu-icon-load-c ivu-load-loop" :class="[prefixCls + '-icon', prefixCls + '-icon-validate']" v-if="!icon"></i> | ||
8 | + </transition> | ||
7 | <input | 9 | <input |
8 | :type="type" | 10 | :type="type" |
9 | :class="inputClasses" | 11 | :class="inputClasses" |
@@ -12,17 +14,17 @@ | @@ -12,17 +14,17 @@ | ||
12 | :maxlength="maxlength" | 14 | :maxlength="maxlength" |
13 | :readonly="readonly" | 15 | :readonly="readonly" |
14 | :name="name" | 16 | :name="name" |
15 | - v-model="value" | 17 | + :value="currentValue" |
16 | :number="number" | 18 | :number="number" |
17 | @keyup.enter="handleEnter" | 19 | @keyup.enter="handleEnter" |
18 | @focus="handleFocus" | 20 | @focus="handleFocus" |
19 | @blur="handleBlur" | 21 | @blur="handleBlur" |
20 | - @change="handleChange"> | ||
21 | - <div :class="[prefixCls + '-group-append']" v-if="append" v-show="slotReady" v-el:append><slot name="append"></slot></div> | 22 | + @input="handleInput"> |
23 | + <div :class="[prefixCls + '-group-append']" v-if="append" v-show="slotReady" ref="append"><slot name="append"></slot></div> | ||
22 | </template> | 24 | </template> |
23 | <textarea | 25 | <textarea |
24 | v-else | 26 | v-else |
25 | - v-el:textarea | 27 | + ref="textarea" |
26 | :class="textareaClasses" | 28 | :class="textareaClasses" |
27 | :style="textareaStyles" | 29 | :style="textareaStyles" |
28 | :placeholder="placeholder" | 30 | :placeholder="placeholder" |
@@ -31,11 +33,11 @@ | @@ -31,11 +33,11 @@ | ||
31 | :maxlength="maxlength" | 33 | :maxlength="maxlength" |
32 | :readonly="readonly" | 34 | :readonly="readonly" |
33 | :name="name" | 35 | :name="name" |
34 | - v-model="value" | 36 | + :value="value" |
35 | @keyup.enter="handleEnter" | 37 | @keyup.enter="handleEnter" |
36 | @focus="handleFocus" | 38 | @focus="handleFocus" |
37 | @blur="handleBlur" | 39 | @blur="handleBlur" |
38 | - @change="handleChange"> | 40 | + @input="handleInput"> |
39 | </textarea> | 41 | </textarea> |
40 | </div> | 42 | </div> |
41 | </template> | 43 | </template> |
@@ -55,8 +57,7 @@ | @@ -55,8 +57,7 @@ | ||
55 | }, | 57 | }, |
56 | value: { | 58 | value: { |
57 | type: [String, Number], | 59 | type: [String, Number], |
58 | - default: '', | ||
59 | -// twoWay: true | 60 | + default: '' |
60 | }, | 61 | }, |
61 | size: { | 62 | size: { |
62 | validator (value) { | 63 | validator (value) { |
@@ -97,6 +98,7 @@ | @@ -97,6 +98,7 @@ | ||
97 | }, | 98 | }, |
98 | data () { | 99 | data () { |
99 | return { | 100 | return { |
101 | + currentValue: this.value, | ||
100 | prefixCls: prefixCls, | 102 | prefixCls: prefixCls, |
101 | prepend: true, | 103 | prepend: true, |
102 | append: true, | 104 | append: true, |
@@ -146,11 +148,24 @@ | @@ -146,11 +148,24 @@ | ||
146 | }, | 148 | }, |
147 | handleBlur () { | 149 | handleBlur () { |
148 | this.$emit('on-blur'); | 150 | this.$emit('on-blur'); |
149 | - this.$dispatch('on-form-blur', this.value); | 151 | + // todo 事件 |
152 | +// this.$dispatch('on-form-blur', this.currentValue); | ||
150 | }, | 153 | }, |
151 | - handleChange (event) { | 154 | + handleInput (event) { |
155 | + const value = event.target.value; | ||
156 | + this.$emit('input', value); | ||
157 | + this.setCurrentValue(value); | ||
152 | this.$emit('on-change', event); | 158 | this.$emit('on-change', event); |
153 | }, | 159 | }, |
160 | + setCurrentValue (value) { | ||
161 | + if (value === this.currentValue) return; | ||
162 | + this.$nextTick(() => { | ||
163 | + this.resizeTextarea(); | ||
164 | + }); | ||
165 | + this.currentValue = value; | ||
166 | + // todo 事件 | ||
167 | +// this.$dispatch('on-form-change', value); | ||
168 | + }, | ||
154 | resizeTextarea () { | 169 | resizeTextarea () { |
155 | const autosize = this.autosize; | 170 | const autosize = this.autosize; |
156 | if (!autosize || this.type !== 'textarea') { | 171 | if (!autosize || this.type !== 'textarea') { |
@@ -160,30 +175,24 @@ | @@ -160,30 +175,24 @@ | ||
160 | const minRows = autosize.minRows; | 175 | const minRows = autosize.minRows; |
161 | const maxRows = autosize.maxRows; | 176 | const maxRows = autosize.maxRows; |
162 | 177 | ||
163 | - this.textareaStyles = calcTextareaHeight(this.$els.textarea, minRows, maxRows); | ||
164 | - }, | ||
165 | - init () { | ||
166 | - if (this.type !== 'textarea') { | ||
167 | - this.prepend = this.$els.prepend.innerHTML !== ''; | ||
168 | - this.append = this.$els.append.innerHTML !== ''; | ||
169 | - } else { | ||
170 | - this.prepend = false; | ||
171 | - this.append = false; | ||
172 | - } | ||
173 | - this.slotReady = true; | ||
174 | - this.resizeTextarea(); | 178 | + this.textareaStyles = calcTextareaHeight(this.$refs.textarea, minRows, maxRows); |
175 | } | 179 | } |
176 | }, | 180 | }, |
177 | watch: { | 181 | watch: { |
178 | - value () { | ||
179 | - this.$nextTick(() => { | ||
180 | - this.resizeTextarea(); | ||
181 | - }); | ||
182 | - this.$dispatch('on-form-change', this.value); | 182 | + value (val) { |
183 | + this.setCurrentValue(val); | ||
183 | } | 184 | } |
184 | }, | 185 | }, |
185 | - compiled () { | ||
186 | - this.$nextTick(() => this.init()); | 186 | + mounted () { |
187 | + if (this.type !== 'textarea') { | ||
188 | + this.prepend = this.$slots.prepend !== undefined; | ||
189 | + this.append = this.$slots.append !== undefined; | ||
190 | + } else { | ||
191 | + this.prepend = false; | ||
192 | + this.append = false; | ||
193 | + } | ||
194 | + this.slotReady = true; | ||
195 | + this.resizeTextarea(); | ||
187 | } | 196 | } |
188 | }; | 197 | }; |
189 | </script> | 198 | </script> |
src/index.js
@@ -17,7 +17,7 @@ import Button from './components/button'; | @@ -17,7 +17,7 @@ import Button from './components/button'; | ||
17 | // import Dropdown from './components/dropdown'; | 17 | // import Dropdown from './components/dropdown'; |
18 | // import Form from './components/form'; | 18 | // import Form from './components/form'; |
19 | import Icon from './components/icon'; | 19 | import Icon from './components/icon'; |
20 | -// import Input from './components/input'; | 20 | +import Input from './components/input'; |
21 | // import InputNumber from './components/input-number'; | 21 | // import InputNumber from './components/input-number'; |
22 | // import LoadingBar from './components/loading-bar'; | 22 | // import LoadingBar from './components/loading-bar'; |
23 | // import Menu from './components/menu'; | 23 | // import Menu from './components/menu'; |
@@ -73,6 +73,7 @@ const iview = { | @@ -73,6 +73,7 @@ const iview = { | ||
73 | // Collapse, | 73 | // Collapse, |
74 | Icon, | 74 | Icon, |
75 | // iInput: Input, | 75 | // iInput: Input, |
76 | + Input, | ||
76 | // InputNumber, | 77 | // InputNumber, |
77 | // LoadingBar, | 78 | // LoadingBar, |
78 | // Menu, | 79 | // Menu, |
test/app.vue
@@ -27,6 +27,7 @@ li + li { | @@ -27,6 +27,7 @@ li + li { | ||
27 | <li><router-link to="/affix">Affix</router-link></li> | 27 | <li><router-link to="/affix">Affix</router-link></li> |
28 | <li><router-link to="/grid">Grid</router-link></li> | 28 | <li><router-link to="/grid">Grid</router-link></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 | </ul> | 31 | </ul> |
31 | </nav> | 32 | </nav> |
32 | <router-view></router-view> | 33 | <router-view></router-view> |
test/main.js
@@ -28,6 +28,10 @@ const router = new VueRouter({ | @@ -28,6 +28,10 @@ const router = new VueRouter({ | ||
28 | { | 28 | { |
29 | path: '/button', | 29 | path: '/button', |
30 | component: require('./routers/button.vue') | 30 | component: require('./routers/button.vue') |
31 | + }, | ||
32 | + { | ||
33 | + path: '/input', | ||
34 | + component: require('./routers/input.vue') | ||
31 | } | 35 | } |
32 | ] | 36 | ] |
33 | }); | 37 | }); |
test/routers/input.vue
1 | <template> | 1 | <template> |
2 | - <Input-number :max="10" :min="1" :value="1"></Input-number> | ||
3 | - <br><br> | ||
4 | - <i-input type="textarea" :autosize="true" placeholder="请输入..."></i-input> | ||
5 | - <i-input type="textarea" :autosize="{minRows: 2,maxRows: 5}" placeholder="请输入..."></i-input> | ||
6 | - <i-input name="a" icon="ios-clock-outline" @on-focus="focus" @on-blur="blur" readonly style="width:200px;" :value.sync="v" @on-enter="enter" @on-click="iconclick" size="large" placeholder="请输入"></i-input> | ||
7 | - <i-input icon="ios-clock-outline" style="width:200px;" :value.sync="v" @on-enter="enter" placeholder="请输入"></i-input> | ||
8 | - <i-input name="b" icon="ios-clock-outline" style="width:200px;" :value.sync="v" @on-enter="enter" size="small" placeholder="请输入"></i-input> | ||
9 | - <br> | ||
10 | - <br> | ||
11 | - <i-input style="width:200px;" :value.sync="v" @on-enter="enter" size="large" placeholder="请输入"></i-input> | ||
12 | - <i-input style="width:200px;" :value.sync="v" @on-enter="enter" placeholder="请输入"></i-input> | ||
13 | - <i-input style="width:200px;" :value.sync="v" @on-enter="enter" @on-change="change" size="small" placeholder="请输入"></i-input> | ||
14 | - {{ v }} | ||
15 | - <br> | ||
16 | - <br> | ||
17 | - <i-input readonly placeholder="this is something" style="width:200px;" :value.sync="t" type="textarea" :autosize="autosize"></i-input> | ||
18 | - {{ t }} | ||
19 | - <br> | ||
20 | - <br> | ||
21 | - <div style="width: 400px"> | ||
22 | - <i-input :value.sync="v" type="password"> | ||
23 | - <span slot="prepend">http://</span> | ||
24 | - <span slot="append"> | ||
25 | - <i-button icon="ios-search"></i-button> | ||
26 | - </span> | ||
27 | - </i-input> | 2 | + <div> |
3 | + <Input v-model="value" placeholder="请输入..." style="width: 300px" icon="ios-clock-outline"></Input> | ||
4 | + <input type="text" v-model="value"> | ||
5 | + {{ value }} | ||
6 | + <!--<Input v-model="value">--> | ||
7 | + <!--<span slot="prepend">http://</span>--> | ||
8 | + <!--<span slot="append">.com</span>--> | ||
9 | + <!--</Input>--> | ||
28 | <br> | 10 | <br> |
29 | - <i-input :value.sync="v"> | ||
30 | - <span slot="prepend">http://</span> | ||
31 | - <span slot="append"><Icon type="ios-search"></Icon></span> | ||
32 | - </i-input> | 11 | + <Input type="textarea" v-model="value" placeholder="请输入..."></Input> |
12 | + <Input type="textarea" v-model="value" :rows="4" placeholder="请输入..."></Input> | ||
33 | <br> | 13 | <br> |
34 | - <i-input :value.sync="v" size="small"> | ||
35 | - <span slot="prepend">http://</span> | ||
36 | - <span slot="append"><Icon type="ios-search"></Icon></span> | ||
37 | - </i-input> | ||
38 | - | ||
39 | <br> | 14 | <br> |
40 | - <i-input :value.sync="v" size="large"> | ||
41 | - <i-select :model.sync="select1" slot="prepend" style="width: 80px"> | ||
42 | - <i-option value="http">http://</i-option> | ||
43 | - <i-option value="https">https://</i-option> | ||
44 | - </i-select> | ||
45 | - <i-select :model.sync="select2" slot="append" style="width: 70px"> | ||
46 | - <i-option value="com">.com</i-option> | ||
47 | - <i-option value="cn">.cn</i-option> | ||
48 | - <i-option value="net">.net</i-option> | ||
49 | - <i-option value="io">.io</i-option> | ||
50 | - </i-select> | ||
51 | - </i-input> | ||
52 | - <br> | ||
53 | - <i-input :value.sync="v"> | ||
54 | - <i-select :model.sync="select1" slot="prepend" style="width: 80px"> | ||
55 | - <i-option value="http">http://</i-option> | ||
56 | - <i-option value="https">https://</i-option> | ||
57 | - </i-select> | ||
58 | - <i-select :model.sync="select2" slot="append" style="width: 70px"> | ||
59 | - <i-option value="com">.com</i-option> | ||
60 | - <i-option value="cn">.cn</i-option> | ||
61 | - <i-option value="net">.net</i-option> | ||
62 | - <i-option value="io">.io</i-option> | ||
63 | - </i-select> | ||
64 | - </i-input> | ||
65 | - <br> | ||
66 | - <i-input :value.sync="v" size="small"> | ||
67 | - <i-select :model.sync="select1" slot="prepend" style="width: 80px"> | ||
68 | - <i-option value="http">http://</i-option> | ||
69 | - <i-option value="https">https://</i-option> | ||
70 | - </i-select> | ||
71 | - <i-select :model.sync="select2" slot="append" style="width: 70px"> | ||
72 | - <i-option value="com">.com</i-option> | ||
73 | - <i-option value="cn">.cn</i-option> | ||
74 | - <i-option value="net">.net</i-option> | ||
75 | - <i-option value="io">.io</i-option> | ||
76 | - </i-select> | ||
77 | - </i-input> | ||
78 | - <Input-number :value="2" size="small"></Input-number> | ||
79 | - <Input-number :value="2"></Input-number> | ||
80 | - <Input-number :value="2" size="large"></Input-number> | ||
81 | - <i-input type="password"></i-input> | 15 | + <Input type="textarea" v-model="value" :autosize="true" placeholder="请输入..."></Input> |
16 | + <Input type="textarea" v-model="value" :autosize="{minRows: 2,maxRows: 5}" placeholder="请输入..."></Input> | ||
82 | </div> | 17 | </div> |
83 | </template> | 18 | </template> |
84 | <script> | 19 | <script> |
85 | - import { iInput, Icon, iButton, iSelect, iOption, InputNumber } from 'iview'; | ||
86 | - | ||
87 | export default { | 20 | export default { |
88 | - components: { | ||
89 | - iInput, | ||
90 | - Icon, | ||
91 | - iButton, | ||
92 | - iSelect, | ||
93 | - iOption, | ||
94 | - InputNumber | ||
95 | - }, | ||
96 | - props: { | ||
97 | - | ||
98 | - }, | ||
99 | data () { | 21 | data () { |
100 | return { | 22 | return { |
101 | - v: 'hello', | ||
102 | - t: '', | ||
103 | - autosize: { | ||
104 | - minRows: 2, | ||
105 | - maxRows: 5 | ||
106 | - }, | ||
107 | - select1: 'http', | ||
108 | - select2: 'com' | ||
109 | - } | ||
110 | - }, | ||
111 | - computed: { | ||
112 | - | ||
113 | - }, | ||
114 | - methods: { | ||
115 | - enter () { | ||
116 | - console.log(123) | ||
117 | - }, | ||
118 | - iconclick () { | ||
119 | - console.log('iconclicked') | ||
120 | - }, | ||
121 | - change (val) { | ||
122 | - console.log(val) | ||
123 | - }, | ||
124 | - focus () { | ||
125 | - this.$Message.info('focus'); | ||
126 | - }, | ||
127 | - blur () { | ||
128 | - this.$Message.info('blur'); | 23 | + value: '' |
129 | } | 24 | } |
130 | } | 25 | } |
131 | } | 26 | } |
132 | -</script> | ||
133 | \ No newline at end of file | 27 | \ No newline at end of file |
28 | +</script> |