index.vue 7.1 KB
Newer Older
fxy060608's avatar
fxy060608 已提交
1
<template>
2 3 4
  <uni-input
    @change.stop
    v-on="$listeners"
fxy060608's avatar
fxy060608 已提交
5
  >
6 7 8
    <div
      ref="wrapper"
      class="uni-input-wrapper"
fxy060608's avatar
fxy060608 已提交
9
    >
10
      <div
11
        v-show="!(composing || valueSync.length)"
12 13 14 15
        ref="placeholder"
        :style="placeholderStyle"
        :class="placeholderClass"
        class="uni-input-placeholder"
16 17
        v-text="placeholder"
      />
18 19
      <input
        ref="input"
20
        v-model="valueSync"
21
        v-keyboard
22 23 24
        :disabled="disabled"
        :type="inputType"
        :maxlength="maxlength"
25
        :step="step"
26
        :autofocus="focus"
27
        class="uni-input-input"
28
        autocomplete="off"
29 30 31 32
        @focus="_onFocus"
        @blur="_onBlur"
        @input.stop="_onInput"
        @compositionstart="_onComposition"
fxy060608's avatar
fxy060608 已提交
33
        @compositionend="_onComposition"
34 35
        @keyup.stop="_onKeyup"
      >
fxy060608's avatar
fxy060608 已提交
36 37 38 39 40
    </div>
  </uni-input>
</template>
<script>
import {
41
  baseInput
fxy060608's avatar
fxy060608 已提交
42
} from 'uni-mixins'
43
const INPUT_TYPES = ['text', 'number', 'idcard', 'digit', 'password']
44
const NUMBER_TYPES = ['number', 'digit']
fxy060608's avatar
fxy060608 已提交
45 46
export default {
  name: 'Input',
47
  mixins: [baseInput],
fxy060608's avatar
fxy060608 已提交
48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70
  props: {
    name: {
      type: String,
      default: ''
    },
    type: {
      type: String,
      default: 'text'
    },
    password: {
      type: [Boolean, String],
      default: false
    },
    placeholder: {
      type: String,
      default: ''
    },
    placeholderStyle: {
      type: String,
      default: ''
    },
    placeholderClass: {
      type: String,
71
      default: 'input-placeholder'
fxy060608's avatar
fxy060608 已提交
72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92
    },
    disabled: {
      type: [Boolean, String],
      default: false
    },
    maxlength: {
      type: [Number, String],
      default: 140
    },
    focus: {
      type: [Boolean, String],
      default: false
    },
    confirmType: {
      type: String,
      default: 'done'
    }
  },
  data () {
    return {
      composing: false,
93
      wrapperHeight: 0,
94
      cachedValue: ''
fxy060608's avatar
fxy060608 已提交
95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111
    }
  },
  computed: {
    inputType: function () {
      let type = ''
      switch (this.type) {
        case 'text':
          this.confirmType === 'search' && (type = 'search')
          break
        case 'idcard':
          // TODO 可能要根据不同平台进行区分处理
          type = 'text'
          break
        case 'digit':
          type = 'number'
          break
        default:
112
          type = ~INPUT_TYPES.indexOf(this.type) ? this.type : 'text'
fxy060608's avatar
fxy060608 已提交
113 114 115 116 117 118
          break
      }
      return this.password ? 'password' : type
    },
    step () {
      // 处理部分设备中无法输入小数点的问题
119
      return ~NUMBER_TYPES.indexOf(this.type) ? '0.000000000000000001' : ''
fxy060608's avatar
fxy060608 已提交
120 121 122
    }
  },
  watch: {
123 124
    focus (val) {
      this.$refs.input && this.$refs.input[val ? 'focus' : 'blur']()
fxy060608's avatar
fxy060608 已提交
125 126
    },
    maxlength (value) {
127 128
      const realValue = this.valueSync.slice(0, parseInt(value, 10))
      realValue !== this.valueSync && (this.valueSync = realValue)
fxy060608's avatar
fxy060608 已提交
129 130 131 132 133 134 135 136 137 138
    }
  },
  created () {
    this.$dispatch('Form', 'uni-form-group-update', {
      type: 'add',
      vm: this
    })
  },
  mounted () {
    if (this.confirmType === 'search') {
139
      const formElem = document.createElement('form')
fxy060608's avatar
fxy060608 已提交
140 141 142 143
      formElem.action = ''
      formElem.onsubmit = function () {
        return false
      }
144
      formElem.className = 'uni-input-form'
fxy060608's avatar
fxy060608 已提交
145 146 147 148
      formElem.appendChild(this.$refs.input)
      this.$refs.wrapper.appendChild(formElem)
    }

149 150 151 152 153 154 155 156
    let $vm = this
    while ($vm) {
      const scopeId = $vm.$options._scopeId
      if (scopeId) {
        this.$refs.placeholder.setAttribute(scopeId, '')
      }
      $vm = $vm.$parent
    }
fxy060608's avatar
fxy060608 已提交
157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175
  },
  beforeDestroy () {
    this.$dispatch('Form', 'uni-form-group-update', {
      type: 'remove',
      vm: this
    })
  },
  methods: {
    _onKeyup ($event) {
      if ($event.keyCode === 13) {
        this.$trigger('confirm', $event, {
          value: $event.target.value
        })
      }
    },
    _onInput ($event) {
      if (this.composing) {
        return
      }
176 177 178 179 180

      // 处理部分输入法可以输入其它字符的情况
      if (~NUMBER_TYPES.indexOf(this.type)) {
        if (this.$refs.input.validity && !this.$refs.input.validity.valid) {
          $event.target.value = this.cachedValue
181
          this.valueSync = $event.target.value
182 183
          // 输入非法字符不触发 input 事件
          return
184
        } else {
185
          this.cachedValue = this.valueSync
186 187
        }
      }
fxy060608's avatar
fxy060608 已提交
188

189 190 191 192 193
      // type="number" 不支持 maxlength 属性,因此需要主动限制长度。
      if (this.inputType === 'number') {
        const maxlength = parseInt(this.maxlength, 10)
        if (maxlength > 0 && $event.target.value.length > maxlength) {
          $event.target.value = $event.target.value.slice(0, maxlength)
194
          this.valueSync = $event.target.value
195 196
          // 字符长度超出范围不触发 input 事件
          return
197 198
        }
      }
199 200
      this.$triggerInput($event, {
        value: this.valueSync
fxy060608's avatar
fxy060608 已提交
201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220
      })
    },
    _onFocus ($event) {
      this.$trigger('focus', $event, {
        value: $event.target.value
      })
    },
    _onBlur ($event) {
      this.$trigger('blur', $event, {
        value: $event.target.value
      })
    },
    _onComposition ($event) {
      if ($event.type === 'compositionstart') {
        this.composing = true
      } else {
        this.composing = false
      }
    },
    _resetFormData () {
221
      this.valueSync = ''
fxy060608's avatar
fxy060608 已提交
222 223 224
    },
    _getFormData () {
      return this.name ? {
225
        value: this.valueSync,
fxy060608's avatar
fxy060608 已提交
226 227 228 229 230 231 232
        key: this.name
      } : {}
    }
  }
}
</script>
<style>
233 234 235 236 237 238
uni-input {
  display: block;
  font-size: 16px;
  line-height: 1.4em;
  height: 1.4em;
  min-height: 1.4em;
239
  overflow: hidden;
240
}
fxy060608's avatar
fxy060608 已提交
241

242 243 244
uni-input[hidden] {
  display: none;
}
fxy060608's avatar
fxy060608 已提交
245

246 247 248 249 250 251 252 253 254 255
.uni-input-wrapper,
.uni-input-placeholder,
.uni-input-form,
.uni-input-input {
  outline: none;
  border: none;
  padding: 0;
  margin: 0;
  text-decoration: inherit;
}
fxy060608's avatar
fxy060608 已提交
256

257 258
.uni-input-wrapper,
.uni-input-form {
259
  display: flex;
260 261 262
  position: relative;
  width: 100%;
  height: 100%;
263 264
  flex-direction: column;
  justify-content: center;
265
}
fxy060608's avatar
fxy060608 已提交
266

267
.uni-input-placeholder,
Q
qiang 已提交
268
.uni-input-input {
269 270
  width: 100%;
}
fxy060608's avatar
fxy060608 已提交
271

272
.uni-input-placeholder {
273
  position: absolute;
274
  top: auto !important;
275
  left: 0;
276 277 278 279 280
  color: gray;
  overflow: hidden;
  text-overflow: clip;
  white-space: pre;
  word-break: keep-all;
281
  pointer-events: none;
282
  line-height: inherit;
283
}
fxy060608's avatar
fxy060608 已提交
284

285
.uni-input-input {
286 287
  display: block;
  height: 100%;
288 289
  background: none;
  color: inherit;
290
  opacity: 1;
291
  -webkit-text-fill-color: currentcolor;
292 293 294 295 296 297 298 299
  font: inherit;
  line-height: inherit;
  letter-spacing: inherit;
  text-align: inherit;
  text-indent: inherit;
  text-transform: inherit;
  text-shadow: inherit;
}
fxy060608's avatar
fxy060608 已提交
300

301 302 303
.uni-input-input[type="search"]::-webkit-search-cancel-button {
  display: none;
}
fxy060608's avatar
fxy060608 已提交
304

305 306 307 308 309
.uni-input-input::-webkit-outer-spin-button,
.uni-input-input::-webkit-inner-spin-button {
  -webkit-appearance: none;
  margin: 0;
}
fxy060608's avatar
fxy060608 已提交
310

311 312 313
.uni-input-input[type="number"] {
  -moz-appearance: textfield;
}
314
</style>