提交 4c30e74d 编写于 作者: Q qiang

fix: 修复部分时机获取 input、textarea 组件值不正确的问题 question/115897

上级 c75eaf24
<template> <template>
<uni-input <uni-input v-on="$listeners">
@change.stop
v-on="$listeners"
>
<div <div
ref="wrapper" ref="wrapper"
class="uni-input-wrapper" class="uni-input-wrapper"
...@@ -20,6 +17,7 @@ ...@@ -20,6 +17,7 @@
ref="input" ref="input"
v-model="valueSync" v-model="valueSync"
v-keyboard v-keyboard
v-field
:disabled="disabled" :disabled="disabled"
:type="inputType" :type="inputType"
:maxlength="maxlength" :maxlength="maxlength"
...@@ -27,11 +25,12 @@ ...@@ -27,11 +25,12 @@
:enterkeyhint="confirmType" :enterkeyhint="confirmType"
class="uni-input-input" class="uni-input-input"
autocomplete="off" autocomplete="off"
@change.stop
@focus="_onFocus" @focus="_onFocus"
@blur="_onBlur" @blur="_onBlur"
@input.stop="_onInput" @input.stop="_onInput"
@compositionstart="_onComposition" @compositionstart.stop="_onComposition"
@compositionend="_onComposition" @compositionend.stop="_onComposition"
@keyup.enter.stop="_onKeyup" @keyup.enter.stop="_onKeyup"
> >
<!-- fix: 禁止 readonly 状态获取焦点 --> <!-- fix: 禁止 readonly 状态获取焦点 -->
...@@ -45,7 +44,7 @@ ...@@ -45,7 +44,7 @@
:maxlength="maxlength" :maxlength="maxlength"
:step="step" :step="step"
class="uni-input-input" class="uni-input-input"
@focus="$event=>$event.target.blur()" @focus="($event) => $event.target.blur()"
> >
</div> </div>
</uni-input> </uni-input>
...@@ -164,8 +163,6 @@ export default { ...@@ -164,8 +163,6 @@ export default {
} }
$vm = $vm.$parent $vm = $vm.$parent
} }
this._initField('input')
}, },
beforeDestroy () { beforeDestroy () {
this.$dispatch('Form', 'uni-form-group-update', { this.$dispatch('Form', 'uni-form-group-update', {
...@@ -179,7 +176,7 @@ export default { ...@@ -179,7 +176,7 @@ export default {
value: $event.target.value value: $event.target.value
}) })
}, },
_onInput ($event) { _onInput ($event, force) {
if (this.composing) { if (this.composing) {
return return
} }
...@@ -213,7 +210,7 @@ export default { ...@@ -213,7 +210,7 @@ export default {
} }
this.$triggerInput($event, { this.$triggerInput($event, {
value: this.valueSync value: this.valueSync
}) }, force)
}, },
_onFocus ($event) { _onFocus ($event) {
this.$trigger('focus', $event, { this.$trigger('focus', $event, {
...@@ -221,6 +218,11 @@ export default { ...@@ -221,6 +218,11 @@ export default {
}) })
}, },
_onBlur ($event) { _onBlur ($event) {
// iOS 输入法 compositionend 事件可能晚于 blur
if (this.composing) {
this.composing = false
this._onInput($event, true)
}
this.$trigger('blur', $event, { this.$trigger('blur', $event, {
value: $event.target.value value: $event.target.value
}) })
...@@ -228,7 +230,7 @@ export default { ...@@ -228,7 +230,7 @@ export default {
_onComposition ($event) { _onComposition ($event) {
if ($event.type === 'compositionstart') { if ($event.type === 'compositionstart') {
this.composing = true this.composing = true
} else { } else if (this.composing) {
this.composing = false this.composing = false
// 部分输入法 compositionend 事件可能晚于 input // 部分输入法 compositionend 事件可能晚于 input
this._onInput($event) this._onInput($event)
......
<template> <template>
<uni-textarea <uni-textarea v-on="$listeners">
@change.stop
v-on="$listeners"
>
<div class="uni-textarea-wrapper"> <div class="uni-textarea-wrapper">
<div <div
v-show="!(composition || valueSync.length)" v-show="!(composing || valueSync.length)"
ref="placeholder" ref="placeholder"
:style="placeholderStyle" :style="placeholderStyle"
:class="placeholderClass" :class="placeholderClass"
...@@ -33,14 +30,16 @@ ...@@ -33,14 +30,16 @@
ref="textarea" ref="textarea"
v-model="valueSync" v-model="valueSync"
v-keyboard v-keyboard
v-field
:disabled="disabled" :disabled="disabled"
:maxlength="maxlengthNumber" :maxlength="maxlengthNumber"
:class="{ 'uni-textarea-textarea-fix-margin': fixMargin }" :class="{ 'uni-textarea-textarea-fix-margin': fixMargin }"
:style="{ 'overflow-y': autoHeight ? 'hidden' : 'auto' }" :style="{ 'overflow-y': autoHeight ? 'hidden' : 'auto' }"
:enterkeyhint="confirmType" :enterkeyhint="confirmType"
class="uni-textarea-textarea" class="uni-textarea-textarea"
@compositionstart="_onCompositionstart" @change.stop
@compositionend="_onCompositionend" @compositionstart.stop="_onCompositionstart"
@compositionend.stop="_onCompositionend"
@input.stop="_onInput" @input.stop="_onInput"
@focus="_onFocus" @focus="_onFocus"
@blur="_onBlur" @blur="_onBlur"
...@@ -59,7 +58,7 @@ ...@@ -59,7 +58,7 @@
:class="{ 'uni-textarea-textarea-fix-margin': fixMargin }" :class="{ 'uni-textarea-textarea-fix-margin': fixMargin }"
:style="{ 'overflow-y': autoHeight ? 'hidden' : 'auto' }" :style="{ 'overflow-y': autoHeight ? 'hidden' : 'auto' }"
class="uni-textarea-textarea" class="uni-textarea-textarea"
@focus="$event=>$event.target.blur()" @focus="($event) => $event.target.blur()"
/> />
</div> </div>
</uni-textarea> </uni-textarea>
...@@ -121,7 +120,7 @@ export default { ...@@ -121,7 +120,7 @@ export default {
data () { data () {
return { return {
valueComposition: '', valueComposition: '',
composition: false, composing: false,
focusSync: this.focus, focusSync: this.focus,
height: 0, height: 0,
focusChangeSource: '', focusChangeSource: '',
...@@ -149,7 +148,7 @@ export default { ...@@ -149,7 +148,7 @@ export default {
return isNaN(selectionEnd) ? -1 : selectionEnd return isNaN(selectionEnd) ? -1 : selectionEnd
}, },
valueCompute () { valueCompute () {
return (this.composition ? this.valueComposition : this.valueSync).split('\n') return (this.composing ? this.valueComposition : this.valueSync).split('\n')
}, },
isDone () { isDone () {
return ['done', 'go', 'next', 'search', 'send'].includes(this.confirmType) return ['done', 'go', 'next', 'search', 'send'].includes(this.confirmType)
...@@ -210,8 +209,6 @@ export default { ...@@ -210,8 +209,6 @@ export default {
} }
$vm = $vm.$parent $vm = $vm.$parent
} }
this._initField('textarea')
}, },
beforeDestroy () { beforeDestroy () {
this.$dispatch('Form', 'uni-form-group-update', { this.$dispatch('Form', 'uni-form-group-update', {
...@@ -249,6 +246,11 @@ export default { ...@@ -249,6 +246,11 @@ export default {
} }
}, },
_onBlur: function ($event) { _onBlur: function ($event) {
// iOS 输入法 compositionend 事件可能晚于 blur
if (this.composing) {
this.composing = false
this._onInput($event, true)
}
this.focusSync = false this.focusSync = false
this.$trigger('blur', $event, { this.$trigger('blur', $event, {
value: this.valueSync, value: this.valueSync,
...@@ -256,12 +258,14 @@ export default { ...@@ -256,12 +258,14 @@ export default {
}) })
}, },
_onCompositionstart ($event) { _onCompositionstart ($event) {
this.composition = true this.composing = true
}, },
_onCompositionend ($event) { _onCompositionend ($event) {
this.composition = false if (this.composing) {
// 部分输入法 compositionend 事件可能晚于 input this.composing = false
this._onInput($event) // 部分输入法 compositionend 事件可能晚于 input
this._onInput($event)
}
}, },
// 暂无完成按钮,此功能未实现 // 暂无完成按钮,此功能未实现
_confirm ($event) { _confirm ($event) {
...@@ -280,15 +284,15 @@ export default { ...@@ -280,15 +284,15 @@ export default {
_resize ({ height }) { _resize ({ height }) {
this.height = height this.height = height
}, },
_onInput ($event) { _onInput ($event, force) {
if (this.composition) { if (this.composing) {
this.valueComposition = $event.target.value this.valueComposition = $event.target.value
return return
} }
this.$triggerInput($event, { this.$triggerInput($event, {
value: this.valueSync, value: this.valueSync,
cursor: this.$refs.textarea.selectionEnd cursor: this.$refs.textarea.selectionEnd
}) }, force)
}, },
_getFormData () { _getFormData () {
return { return {
......
...@@ -79,21 +79,31 @@ export default { ...@@ -79,21 +79,31 @@ export default {
this.$emit('update:value', detail.value) this.$emit('update:value', detail.value)
this.$trigger('input', $event, detail) this.$trigger('input', $event, detail)
}, 100) }, 100)
this.$triggerInput = ($event, detail) => { this.$triggerInput = ($event, detail, force) => {
this.__valueChange.cancel() this.__valueChange.cancel()
this.__triggerInput($event, detail) this.__triggerInput($event, detail)
if (force) {
this.__triggerInput.flush()
}
} }
}, },
beforeDestroy () { beforeDestroy () {
this.__valueChange.cancel() this.__valueChange.cancel()
this.__triggerInput.cancel() this.__triggerInput.cancel()
}, },
directives: {
field: {
inserted (el, binding, vnode) {
vnode.context._initField(el)
}
}
},
methods: { methods: {
_getValueString (value) { _getValueString (value) {
return value === null ? '' : String(value) return value === null ? '' : String(value)
}, },
_initField (ref) { _initField (el) {
this._fieldRef = ref this._field = el
startTime = startTime || Date.now() startTime = startTime || Date.now()
if (this.needFocus) { if (this.needFocus) {
this._focus() this._focus()
...@@ -103,7 +113,7 @@ export default { ...@@ -103,7 +113,7 @@ export default {
if (!this.needFocus) { if (!this.needFocus) {
return return
} }
const field = this.$refs[this._fieldRef] const field = this._field
if (!field || (__PLATFORM__ === 'app-plus' && !window.plus)) { if (!field || (__PLATFORM__ === 'app-plus' && !window.plus)) {
setTimeout(this._focus.bind(this), 100) setTimeout(this._focus.bind(this), 100)
return return
...@@ -121,7 +131,7 @@ export default { ...@@ -121,7 +131,7 @@ export default {
} }
}, },
_blur () { _blur () {
const field = this.$refs[this._fieldRef] const field = this._field
field && field.blur() field && field.blur()
} }
} }
......
...@@ -49,13 +49,13 @@ const camelizeRE = /-(\w)/g ...@@ -49,13 +49,13 @@ const camelizeRE = /-(\w)/g
export const camelize = cached((str) => { export const camelize = cached((str) => {
return str.replace(camelizeRE, (_, c) => c ? c.toUpperCase() : '') return str.replace(camelizeRE, (_, c) => c ? c.toUpperCase() : '')
}) })
/** /**
* Capitalize a string. * Capitalize a string.
*/ */
export const capitalize = cached((str) => { export const capitalize = cached((str) => {
return str.charAt(0).toUpperCase() + str.slice(1) return str.charAt(0).toUpperCase() + str.slice(1)
}) })
export function setProperties (item, props, propsData) { export function setProperties (item, props, propsData) {
props.forEach(function (name) { props.forEach(function (name) {
...@@ -107,10 +107,12 @@ export function debounce (fn, delay) { ...@@ -107,10 +107,12 @@ export function debounce (fn, delay) {
export function throttle (fn, wait) { export function throttle (fn, wait) {
let last = 0 let last = 0
let timeout let timeout
let waitCallback
const newFn = function (...arg) { const newFn = function (...arg) {
const now = Date.now() const now = Date.now()
clearTimeout(timeout) clearTimeout(timeout)
const waitCallback = () => { waitCallback = () => {
waitCallback = null
last = now last = now
fn.apply(this, arg) fn.apply(this, arg)
} }
...@@ -122,6 +124,11 @@ export function throttle (fn, wait) { ...@@ -122,6 +124,11 @@ export function throttle (fn, wait) {
} }
newFn.cancel = function () { newFn.cancel = function () {
clearTimeout(timeout) clearTimeout(timeout)
waitCallback = null
}
newFn.flush = function () {
clearTimeout(timeout)
waitCallback && waitCallback()
} }
return newFn return newFn
} }
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册