Skip to content

Commit

Permalink
fix: 解决 Textarea 因为输入法原因造成 onChange 不报或误报问题
Browse files Browse the repository at this point in the history
  • Loading branch information
cncolder committed Jun 13, 2020
1 parent e5e04e1 commit 5b1002a
Show file tree
Hide file tree
Showing 2 changed files with 63 additions and 7 deletions.
12 changes: 5 additions & 7 deletions src/Textarea.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
import React, { useRef, useMemo } from 'react'
import React, { useMemo } from 'react'
import Taro from '@tarojs/taro'
import classNames from 'classnames'
import { View, Textarea as _Textarea, CommonEventFunction } from '@tarojs/components'
import { TextareaProps as _TextareaProps } from '@tarojs/components/types/Textarea'
import { View, CommonEventFunction } from '@tarojs/components'
import { AtTextareaProps } from 'taro-ui/types/textarea'

import { TextareaEnhance, TextareaEnhanceProps } from './TextareaEnhance'
import '../style/Textarea.scss'

export interface TextareaProps
extends Omit<_TextareaProps, 'className' | 'value' | 'focus' | 'onInput'>,
extends Omit<TextareaEnhanceProps, 'className' | 'value' | 'focus' | 'onInput'>,
Pick<AtTextareaProps, 'count' | 'height' | 'textOverflowForbidden'> {
className?: string
style?: React.CSSProperties
Expand Down Expand Up @@ -57,19 +57,17 @@ export const Textarea: React.FC<TextareaProps> = (props) => {

return (
<View className={rootCls} style={style}>
<_Textarea
<TextareaEnhance
ref={textareaRef as any}
className="at-textarea__textarea"
style={textareaStyle}
placeholderClass={placeholderCls}
cursorSpacing={cursorSpacing}
value={value}
// confirmType="完成"
/* 兼容之前的版本 */
maxlength={actualMaxLength}
focus={autoFocus}
onInput={onChange}
// showCount={false}
{...rest}
/>
{count && (
Expand Down
58 changes: 58 additions & 0 deletions src/TextareaEnhance.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import React, { useRef, useCallback } from 'react'
import { Textarea } from '@tarojs/components'
import { TextareaProps } from '@tarojs/components/types/Textarea'

export interface TextareaEnhanceProps extends TextareaProps {
/**
* onBlur/onConfirm 事件也会触发 onChange. 如果 value 与最后一次 onChange 事件相同则跳过.
*
* @default true
*/
mergeChangeEvent?: boolean
}

/**
* Textarea 升级版.
*
* - mergeChangeEvent onBlur/onConfirm 事件也会触发 onChange.
*
* 某些输入法(不只是中文), 输入中的文字并没有真正进入 Textarea 中, 只是浮动在上面的输入法自带 UI 控件.
* 另一些中文输入法会在词语联想过程中提前把拼音输入进输入框内.
* 这两种情况都会造成 onInput 事件不触发或传递错误的值.
* Textarea 组件的 onBlur/onConfirm 事件中汇报的值永远是正确的最终值.
*/
export const TextareaEnhance: React.FC<TextareaEnhanceProps> = (props) => {
const { mergeChangeEvent = true, onInput, onBlur, onConfirm, ...rest } = props

const previousInputValue = useRef<string>()

const handleInput = useCallback<typeof onInput>(
(e) => {
previousInputValue.current = e.detail.value
onInput(e)
},
[onInput]
)

const handleBlur = useCallback<typeof onBlur>(
(e) => {
if (mergeChangeEvent && e.detail.value !== previousInputValue.current) {
onInput({ ...e, detail: { ...e.detail, keyCode: 0 } })
}
onBlur(e)
},
[onBlur, mergeChangeEvent]
)

const handleConfirm = useCallback<typeof onConfirm>(
(e) => {
if (mergeChangeEvent && e.detail.value !== previousInputValue.current) {
onInput({ ...e, detail: { ...e.detail, keyCode: 0, cursor: 0 } })
}
onConfirm(e)
},
[onConfirm, mergeChangeEvent]
)

return <Textarea onInput={(e) => handleInput} onBlur={handleBlur} onConfirm={handleConfirm} {...rest} />
}

0 comments on commit 5b1002a

Please sign in to comment.