Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: 修复IOS16及以上连续输入小数点自动删除数字的bug #4804

Merged
merged 3 commits into from May 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion packages/uni-components/src/helpers/useField.ts
Expand Up @@ -189,7 +189,7 @@ export const emit = [

type Props = ExtractPropTypes<typeof props>

interface State {
export interface State {
value: string
maxlength: number
focus: boolean | string
Expand Down
95 changes: 67 additions & 28 deletions packages/uni-components/src/vue/input/index.tsx
Expand Up @@ -6,6 +6,7 @@ import {
props as fieldProps,
emit as fieldEmit,
useField,
type State,
} from '../../helpers/useField'

const props = /*#__PURE__*/ extend({}, fieldProps, {
Expand All @@ -19,6 +20,30 @@ const props = /*#__PURE__*/ extend({}, fieldProps, {
},
})

function resolveDigitDecimalPoint(
event: InputEvent,
cache: Ref<string>,
state: State,
input: HTMLInputElement
) {
if ((event as InputEvent).data === '.') {
// 解决可重复输入小数点的问题
if (__PLATFORM__ === 'app') {
if (cache.value.slice(-1) === '.') {
state.value = input.value = cache.value = cache.value.slice(0, -1)
return false
} else if (cache.value.includes('.')) {
state.value = input.value = cache.value
return false
}
}
if (cache.value) {
cache.value += '.'
return false
}
}
}

export class UniInputElement extends UniElement {
focus(options?: FocusOptions | undefined): void {
this.querySelector('input')?.focus(options)
Expand Down Expand Up @@ -72,7 +97,6 @@ export default /*#__PURE__*/ defineBuiltInComponent({
: 0
return AUTOCOMPLETES[index]
})

let cache = ref('')
let resetCache: (() => void) | null
const rootRef: Ref<HTMLElement | null> = ref(null)
Expand Down Expand Up @@ -102,37 +126,42 @@ export default /*#__PURE__*/ defineBuiltInComponent({
return false
}
// 处理小数点
if (cache.value) {
if (cache.value.indexOf('.') !== -1) {
// 删除到小数点时
if (
(event as InputEvent).data !== '.' &&
(event as InputEvent).inputType === 'deleteContentBackward'
) {
const dotIndex = cache.value.indexOf('.')
cache.value =
input.value =
state.value =
cache.value.slice(0, dotIndex)
return true
}
} else if ((event as InputEvent).data === '.') {
// 输入小数点时
cache.value += '.'
resetCache = () => {
cache.value = input.value = cache.value.slice(0, -1)
}
input.addEventListener('blur', resetCache)
return false
}
}
const res = resolveDigitDecimalPoint(
event as InputEvent,
cache,
state,
input
)
if (typeof res === 'boolean') return res
cache.value =
state.value =
input.value =
cache.value === '-' ? '' : cache.value
// 输入非法字符不触发 input 事件
return false
} else {
// 处理小数点
const res = resolveDigitDecimalPoint(
event as InputEvent,
cache,
state,
input
)
if (typeof res === 'boolean') return res

if (cache.value === input.value) return false

if (__PLATFORM__ === 'app') {
// iOS 会带着 . 传递给 input
if (
(event as InputEvent).inputType === 'deleteContentBackward' &&
plus.os.name === 'iOS'
) {
input.value.slice(-1) === '.' &&
(input.value = input.value.slice(0, -1))
}
}

cache.value = input.value
}

Expand All @@ -150,7 +179,7 @@ export default /*#__PURE__*/ defineBuiltInComponent({
() => state.value,
(value) => {
if (props.type === 'number' && !(cache.value === '-' && value === '')) {
cache.value = value
cache.value = value.toString()
}
}
)
Expand Down Expand Up @@ -216,7 +245,11 @@ export default /*#__PURE__*/ defineBuiltInComponent({
<input
key="input"
ref={fieldRef}
v-model={state.value}
value={state.value}
onInput={(event: Event) => {
state.value = (event.target as HTMLInputElement).value.toString()
}}
// v-model={($event) => {state.value = $event.toString()}}
disabled={!!props.disabled}
type={type.value}
maxlength={state.maxlength}
Expand All @@ -235,7 +268,13 @@ export default /*#__PURE__*/ defineBuiltInComponent({
<uni-input ref={rootRef}>
<div class="uni-input-wrapper">
<div
v-show={!(state.value.length || cache.value === '-')}
v-show={
!(
state.value.length ||
cache.value === '-' ||
cache.value.includes('.')
)
}
{...scopedAttrsState.attrs}
style={props.placeholderStyle}
class={['uni-input-placeholder', props.placeholderClass]}
Expand Down