Henry Henry
  • JavaScript
  • TypeScript
  • Vue
  • ElementUI
  • React
  • HTML
  • CSS
  • 技术文档
  • GitHub 技巧
  • Nodejs
  • Chrome
  • VSCode
  • Other
  • Mac
  • Windows
  • Linux
  • Vim
  • VSCode
  • Chrome
  • iTerm
  • Mac
  • Obsidian
  • lazygit
  • Vim 技巧
  • 分类
  • 标签
  • 归档
  • 网站
  • 资源
  • Vue 资源
GitHub (opens new window)

Henry

小学生中的前端大佬
  • JavaScript
  • TypeScript
  • Vue
  • ElementUI
  • React
  • HTML
  • CSS
  • 技术文档
  • GitHub 技巧
  • Nodejs
  • Chrome
  • VSCode
  • Other
  • Mac
  • Windows
  • Linux
  • Vim
  • VSCode
  • Chrome
  • iTerm
  • Mac
  • Obsidian
  • lazygit
  • Vim 技巧
  • 分类
  • 标签
  • 归档
  • 网站
  • 资源
  • Vue 资源
GitHub (opens new window)
  • JavaScript

  • TypeScript

  • Vue

  • ElementUI

  • React

  • AntD

    • 基于 AntD 封装的与原生事件一致的 Input 组件
      • 封装背景
      • 定义 Props
      • 在 state 中定义 value 与 oldValue,值都是 props.value
      • 监听 value,更新 state.value
      • 监听 onChange 事件,回调里更新 state.value,并调用 onInput 回调
      • 监听 onBlur 事件,回调里判断 value 与 oldValue 是否相同,并做相应处理
      • 处理 ref 传递
    • 基于 AntD 封装的 TextEllipsis
    • 基于 AntD 封装的可编辑 tabs
  • 前端
  • AntD
Henry
2022-08-03
目录

基于 AntD 封装的与原生事件一致的 Input 组件

# 封装背景

antd 的 Input 只有 onChange 这一个数据变化的事件,而且是只要数据变化就触发;而原生 input 的 onchange 事件是在 input 失去焦点的时候才会触发,oninput 事件在用户输入时触发,它是在元素值发生变化时立即触发

所以 antd Input 的 onChange 其实是原生的 oninput 事件,没有 onchange 事件,而我们有时候是需要这种场景的

故需要封装一个与原生事件一致的的 Input 组件

# 定义 Props

import { InputProps } from 'antd/lib/input'

type Value = string | number

export interface RealInputProps extends Omit<InputProps, 'onChange' | 'onInput' | 'value'> {
  value: Value // 默认值
  onChange?: (value: string) => void // input 失去焦点的时候才会触发
  onInput?: (value: string) => void // 元素值发生变化时立即触发
}

interface State {
  value: Value
  oldValue: Value
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14

Omit:

Construct a type with the properties of T except for those in type K.

type Omit<T, K extends string | number | symbol> = { [P in Exclude<keyof T, K>]: T[P]; }

# 在 state 中定义 value 与 oldValue,值都是 props.value

const { value, onChange, onInput, ...rest } = props
const valueTrim = `${value}`.trim()

const [state, updateState] = useImmer<State>({
  value: valueTrim,
  oldValue: valueTrim
})
1
2
3
4
5
6
7

# 监听 value,更新 state.value

useEffect(() => {
  updateState(draft => {
    draft.value = `${value}`.trim()
  })
}, [value])
1
2
3
4
5

# 监听 onChange 事件,回调里更新 state.value,并调用 onInput 回调

const handleChange = e => {
  const value = e.target.value
  updateState(draft => {
    draft.value = value
  })
  typeof onInput === 'function' && onInput(value)
}
1
2
3
4
5
6
7

# 监听 onBlur 事件,回调里判断 value 与 oldValue 是否相同,并做相应处理

const handleBlur = () => {
  let { oldValue, value } = state
  value = `${value}`.trim()
  updateState(draft => {
    draft.value = value
  })
  if (oldValue != value) {
    updateState(draft => {
      draft.oldValue = value
    })
    typeof onChange === 'function' && onChange(value)
  }
}
1
2
3
4
5
6
7
8
9
10
11
12
13

# 处理 ref 传递

export default forwardRef(RealInput)
1
编辑 (opens new window)
上次更新: 5/27/2023, 1:02:05 PM
Hello React
基于 AntD 封装的 TextEllipsis

← Hello React 基于 AntD 封装的 TextEllipsis→

最近更新
01
version 1.15
07-01
02
version 1.14
06-27
03
version 1.13
06-27
更多文章>
Theme by Vdoing | Copyright © 2017-2023 HenryTSZ | MIT License
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式