未验证 提交 1461bf51 编写于 作者: S simpleStyle 提交者: GitHub

feat: input组件支持name属性 (#427)

* feat: input组件支持name属性

* feat: input组件支持ref属性获取input实例

* feat: 新增name属性的doc文档

* feat: 新增ref新特性支持获取input实例
上级 24ccf123
...@@ -4,8 +4,6 @@ exports[`input props test 1`] = ` ...@@ -4,8 +4,6 @@ exports[`input props test 1`] = `
<div> <div>
<div <div
class="nut-input nut-input-border " class="nut-input nut-input-border "
iconclassprefix="nut-icon"
iconfontclassname="nutui-iconfont"
> >
<div <div
class="nut-input-label " class="nut-input-label "
...@@ -26,6 +24,7 @@ exports[`input props test 1`] = ` ...@@ -26,6 +24,7 @@ exports[`input props test 1`] = `
<input <input
class="input-text" class="input-text"
maxlength="9999" maxlength="9999"
name="text"
placeholder="请输入文字" placeholder="请输入文字"
style="text-align: left;" style="text-align: left;"
type="text" type="text"
......
...@@ -6,7 +6,12 @@ import Button from '@/packages/button' ...@@ -6,7 +6,12 @@ import Button from '@/packages/button'
test('input props test', () => { test('input props test', () => {
const { container } = render( const { container } = render(
<Input label="文本" placeholder="请输入文字" defaultValue="初始文本" /> <Input
name="text"
label="文本"
placeholder="请输入文字"
defaultValue="初始文本"
/>
) )
expect(container.querySelector('.label-string')?.innerHTML).toBe('文本') expect(container.querySelector('.label-string')?.innerHTML).toBe('文本')
expect(container.querySelector('.input-text')).toHaveAttribute( expect(container.querySelector('.input-text')).toHaveAttribute(
...@@ -17,6 +22,7 @@ test('input props test', () => { ...@@ -17,6 +22,7 @@ test('input props test', () => {
'value', 'value',
'初始文本' '初始文本'
) )
expect(container.querySelector('.input-text')).toHaveAttribute('name', 'text')
expect(container.querySelector('.input-text')).toHaveAttribute('type', 'text') expect(container.querySelector('.input-text')).toHaveAttribute('type', 'text')
expect(container).toMatchSnapshot() expect(container).toMatchSnapshot()
}) })
...@@ -48,6 +54,7 @@ test('disabled test', () => { ...@@ -48,6 +54,7 @@ test('disabled test', () => {
test('textarea test', () => { test('textarea test', () => {
const { container } = render( const { container } = render(
<Input <Input
name="textarea"
label="留言" label="留言"
placeholder="留言" placeholder="留言"
type="textarea" type="textarea"
...@@ -56,6 +63,10 @@ test('textarea test', () => { ...@@ -56,6 +63,10 @@ test('textarea test', () => {
maxlength="50" maxlength="50"
/> />
) )
expect(container.querySelector('.input-text')).toHaveAttribute(
'name',
'textarea'
)
expect(container.querySelector('.input-text')).toHaveAttribute( expect(container.querySelector('.input-text')).toHaveAttribute(
'maxlength', 'maxlength',
'50' '50'
...@@ -159,7 +170,7 @@ test('slotButton test', () => { ...@@ -159,7 +170,7 @@ test('slotButton test', () => {
/> />
) )
expect(container.querySelector('.nut-button__warp')?.innerHTML).toBe( expect(container.querySelector('.nut-button__warp')?.innerHTML).toBe(
'发送验证码' '<div class="text">发送验证码</div>'
) )
}) })
......
...@@ -159,6 +159,7 @@ const InputDemo = () => { ...@@ -159,6 +159,7 @@ const InputDemo = () => {
<div className="demo" style={{ paddingBottom: '20px' }}> <div className="demo" style={{ paddingBottom: '20px' }}>
<h2>{translated.basic}</h2> <h2>{translated.basic}</h2>
<Input <Input
name="text"
label={translated.text} label={translated.text}
placeholder={translated.text} placeholder={translated.text}
defaultValue={value} defaultValue={value}
...@@ -169,29 +170,34 @@ const InputDemo = () => { ...@@ -169,29 +170,34 @@ const InputDemo = () => {
/> />
<h2>{translated.title1}</h2> <h2>{translated.title1}</h2>
<Input <Input
name="text"
label={translated.text} label={translated.text}
placeholder={translated.text} placeholder={translated.text}
defaultValue={state.val1} defaultValue={state.val1}
/> />
<Input <Input
name="password"
label={translated.password} label={translated.password}
placeholder={translated.password} placeholder={translated.password}
defaultValue={state.password} defaultValue={state.password}
type="password" type="password"
/> />
<Input <Input
name="number"
label={translated.number} label={translated.number}
placeholder={translated.number} placeholder={translated.number}
defaultValue={state.number} defaultValue={state.number}
type="number" type="number"
/> />
<Input <Input
name="digit"
label={translated.digit} label={translated.digit}
placeholder={translated.digit} placeholder={translated.digit}
defaultValue={state.digit} defaultValue={state.digit}
type="digit" type="digit"
/> />
<Input <Input
name="tel"
label={translated.tel} label={translated.tel}
placeholder={translated.tel} placeholder={translated.tel}
defaultValue={state.tel} defaultValue={state.tel}
......
...@@ -160,6 +160,7 @@ const InputDemo = () => { ...@@ -160,6 +160,7 @@ const InputDemo = () => {
<div className="demo" style={{ paddingBottom: '20px' }}> <div className="demo" style={{ paddingBottom: '20px' }}>
<h2>{translated.basic}</h2> <h2>{translated.basic}</h2>
<Input <Input
name="text"
label={translated.text} label={translated.text}
placeholder={translated.text} placeholder={translated.text}
defaultValue={value} defaultValue={value}
...@@ -170,29 +171,34 @@ const InputDemo = () => { ...@@ -170,29 +171,34 @@ const InputDemo = () => {
/> />
<h2>{translated.title1}</h2> <h2>{translated.title1}</h2>
<Input <Input
name="text"
label={translated.text} label={translated.text}
placeholder={translated.text} placeholder={translated.text}
defaultValue={state.val1} defaultValue={state.val1}
/> />
<Input <Input
name="password"
label={translated.password} label={translated.password}
placeholder={translated.password} placeholder={translated.password}
defaultValue={state.password} defaultValue={state.password}
type="password" type="password"
/> />
<Input <Input
name="number"
label={translated.number} label={translated.number}
placeholder={translated.number} placeholder={translated.number}
defaultValue={state.number} defaultValue={state.number}
type="number" type="number"
/> />
<Input <Input
name="digit"
label={translated.digit} label={translated.digit}
placeholder={translated.digit} placeholder={translated.digit}
defaultValue={state.digit} defaultValue={state.digit}
type="digit" type="digit"
/> />
<Input <Input
name="tel"
label={translated.tel} label={translated.tel}
placeholder={translated.tel} placeholder={translated.tel}
defaultValue={state.tel} defaultValue={state.tel}
......
...@@ -22,7 +22,7 @@ const App = () => { ...@@ -22,7 +22,7 @@ const App = () => {
const [value, UpdateValue] = useState('') const [value, UpdateValue] = useState('')
return ( return (
<> <>
<Input label="Text" defaultValue={value} placeholder="Text" change={(val) => { <Input name="text" label="Text" defaultValue={value} placeholder="Text" change={(val) => {
UpdateValue(val) UpdateValue(val)
}}/> }}/>
</> </>
...@@ -50,29 +50,34 @@ const App = () => { ...@@ -50,29 +50,34 @@ const App = () => {
return ( return (
<> <>
<Input <Input
name="text"
label="Text" label="Text"
placeholder="Text" placeholder="Text"
defaultValue={state.text} defaultValue={state.text}
/> />
<Input <Input
name="password"
label="Password" label="Password"
placeholder="Password" placeholder="Password"
defaultValue={state.password} defaultValue={state.password}
type="password" type="password"
/> />
<Input <Input
name="number"
label="Number" label="Number"
placeholder="Number" placeholder="Number"
defaultValue={state.number} defaultValue={state.number}
type="number" type="number"
/> />
<Input <Input
name="digit"
label="Digit" label="Digit"
placeholder="Digit" placeholder="Digit"
defaultValue={state.digit} defaultValue={state.digit}
type="digit" type="digit"
/> />
<Input <Input
name="tel"
label="Tel" label="Tel"
placeholder="Tel" placeholder="Tel"
defaultValue={state.tel} defaultValue={state.tel}
...@@ -427,6 +432,8 @@ export default App; ...@@ -427,6 +432,8 @@ export default App;
| ------------ | -------------------------------------- | -------------- | ------- | | ------------ | -------------------------------------- | -------------- | ------- |
| defaultValue | Input value | String | - | | defaultValue | Input value | String | - |
| type | Input type, support all native types and `textarea` `number` `digit` type | String | `text` | | type | Input type, support all native types and `textarea` `number` `digit` type | String | `text` |
| name`v1.3.10` | Used for form submission to obtain data | String | - |
| ref`v1.3.10` | Used to obtain internal input instance ref | RefAttributes | - |
| placeholder | Placeholder when the input box is empty | String | - | | placeholder | Placeholder when the input box is empty | String | - |
| label | Left text | String | - | | label | Left text | String | - |
| labelClass | Left text extra class name | String | - | | labelClass | Left text extra class name | String | - |
......
...@@ -24,7 +24,7 @@ const App = () => { ...@@ -24,7 +24,7 @@ const App = () => {
const [value, UpdateValue] = useState('') const [value, UpdateValue] = useState('')
return ( return (
<> <>
<Input label="文本" defaultValue={value} placeholder="文本" change={(val) => { <Input name="text" label="文本" defaultValue={value} placeholder="文本" change={(val) => {
UpdateValue(val) UpdateValue(val)
}}/> }}/>
</> </>
...@@ -53,29 +53,34 @@ const App = () => { ...@@ -53,29 +53,34 @@ const App = () => {
return ( return (
<> <>
<Input <Input
name="text"
label="文本" label="文本"
placeholder="文本" placeholder="文本"
defaultValue={state.text} defaultValue={state.text}
/> />
<Input <Input
name="password"
label="密码" label="密码"
placeholder="密码" placeholder="密码"
defaultValue={state.password} defaultValue={state.password}
type="password" type="password"
/> />
<Input <Input
name="number"
label="数字" label="数字"
placeholder="数字" placeholder="数字"
defaultValue={state.number} defaultValue={state.number}
type="number" type="number"
/> />
<Input <Input
name="digit"
label="整数" label="整数"
placeholder="整数" placeholder="整数"
defaultValue={state.digit} defaultValue={state.digit}
type="digit" type="digit"
/> />
<Input <Input
name="tel"
label="手机号" label="手机号"
placeholder="手机号" placeholder="手机号"
defaultValue={state.tel} defaultValue={state.tel}
...@@ -421,6 +426,8 @@ export default App; ...@@ -421,6 +426,8 @@ export default App;
| ------------ | -------------------------------------- | -------------- | ------- | | ------------ | -------------------------------------- | -------------- | ------- |
| defaultValue | 初始默认值 | String | - | | defaultValue | 初始默认值 | String | - |
| type | 输入框类型,支持原生 `input` 标签的所有 `type` 属性,另外还支持 `textarea` `number` `digit` | String | `text` | | type | 输入框类型,支持原生 `input` 标签的所有 `type` 属性,另外还支持 `textarea` `number` `digit` | String | `text` |
| name`v1.3.10` | 组件名字,用于表单提交获取数据 | String | - |
| ref`v1.3.10` | 用于获取内部input实例ref | RefAttributes | - |
| placeholder | 输入框为空时占位符 | String | - | | placeholder | 输入框为空时占位符 | String | - |
| label | 左侧文本 | String | - | | label | 左侧文本 | String | - |
| labelClass`v1.2.1` | 左侧文本额外类名 | String | - | | labelClass`v1.2.1` | 左侧文本额外类名 | String | - |
......
...@@ -24,7 +24,7 @@ const App = () => { ...@@ -24,7 +24,7 @@ const App = () => {
const [value, UpdateValue] = useState('') const [value, UpdateValue] = useState('')
return ( return (
<> <>
<Input label="文本" defaultValue={value} placeholder="文本" change={(val) => { <Input name="text" label="文本" defaultValue={value} placeholder="文本" change={(val) => {
UpdateValue(val) UpdateValue(val)
}}/> }}/>
</> </>
...@@ -53,29 +53,34 @@ const App = () => { ...@@ -53,29 +53,34 @@ const App = () => {
return ( return (
<> <>
<Input <Input
name="text"
label="文本" label="文本"
placeholder="文本" placeholder="文本"
defaultValue={state.text} defaultValue={state.text}
/> />
<Input <Input
name="password"
label="密码" label="密码"
placeholder="密码" placeholder="密码"
defaultValue={state.password} defaultValue={state.password}
type="password" type="password"
/> />
<Input <Input
name="number"
label="数字" label="数字"
placeholder="数字" placeholder="数字"
defaultValue={state.number} defaultValue={state.number}
type="number" type="number"
/> />
<Input <Input
name="digit"
label="整数" label="整数"
placeholder="整数" placeholder="整数"
defaultValue={state.digit} defaultValue={state.digit}
type="digit" type="digit"
/> />
<Input <Input
name="tel"
label="手机号" label="手机号"
placeholder="手机号" placeholder="手机号"
defaultValue={state.tel} defaultValue={state.tel}
...@@ -421,6 +426,8 @@ export default App; ...@@ -421,6 +426,8 @@ export default App;
| ------------ | -------------------------------------- | -------------- | ------- | | ------------ | -------------------------------------- | -------------- | ------- |
| defaultValue | 初始默认值 | String | - | | defaultValue | 初始默认值 | String | - |
| type | 输入框类型,支持原生 `input` 标签的所有 `type` 属性,另外还支持 `textarea` `number` `digit` | String | `text` | | type | 输入框类型,支持原生 `input` 标签的所有 `type` 属性,另外还支持 `textarea` `number` `digit` | String | `text` |
| name`v1.3.10` | 组件名字,用于表单提交获取数据 | String | - |
| ref`v1.3.10` | 用于获取内部input实例ref | RefAttributes | - |
| placeholder | 输入框为空时占位符 | String | - | | placeholder | 输入框为空时占位符 | String | - |
| label | 左侧文本 | String | - | | label | 左侧文本 | String | - |
| labelClass | 左侧文本额外类名 | String | - | | labelClass | 左侧文本额外类名 | String | - |
......
...@@ -8,6 +8,8 @@ import React, { ...@@ -8,6 +8,8 @@ import React, {
useLayoutEffect, useLayoutEffect,
MouseEvent, MouseEvent,
HTMLInputTypeAttribute, HTMLInputTypeAttribute,
forwardRef,
useImperativeHandle,
} from 'react' } from 'react'
import { formatNumber } from './util' import { formatNumber } from './util'
...@@ -30,6 +32,7 @@ export type ConfirmTextType = 'send' | 'search' | 'next' | 'go' | 'done' ...@@ -30,6 +32,7 @@ export type ConfirmTextType = 'send' | 'search' | 'next' | 'go' | 'done'
export interface InputProps extends IComponent { export interface InputProps extends IComponent {
type: InputType type: InputType
name: string
defaultValue: any defaultValue: any
placeholder: string placeholder: string
label: string label: string
...@@ -86,6 +89,7 @@ export interface InputProps extends IComponent { ...@@ -86,6 +89,7 @@ export interface InputProps extends IComponent {
const defaultProps = { const defaultProps = {
...ComponentDefaults, ...ComponentDefaults,
type: 'text', type: 'text',
name: '',
defaultValue: '', defaultValue: '',
placeholder: '', placeholder: '',
label: '', label: '',
...@@ -125,11 +129,12 @@ export const Input: FunctionComponent< ...@@ -125,11 +129,12 @@ export const Input: FunctionComponent<
React.HTMLAttributes<HTMLDivElement>, React.HTMLAttributes<HTMLDivElement>,
'onChange' | 'onBlur' | 'onFocus' | 'onClick' 'onChange' | 'onBlur' | 'onFocus' | 'onClick'
> >
> = (props) => { > = forwardRef((props, ref) => {
const { locale } = useConfig() const { locale } = useConfig()
const { const {
children, children,
type, type,
name,
defaultValue, defaultValue,
placeholder, placeholder,
label, label,
...@@ -218,6 +223,10 @@ export const Input: FunctionComponent< ...@@ -218,6 +223,10 @@ export const Input: FunctionComponent<
} }
}, [inputValue]) }, [inputValue])
useImperativeHandle(ref, () => {
return inputRef.current
})
const inputClass = useCallback(() => { const inputClass = useCallback(() => {
const prefixCls = 'nut-input' const prefixCls = 'nut-input'
return [ return [
...@@ -405,6 +414,7 @@ export const Input: FunctionComponent< ...@@ -405,6 +414,7 @@ export const Input: FunctionComponent<
> >
{type === 'textarea' ? ( {type === 'textarea' ? (
<textarea <textarea
name={name}
className="input-text" className="input-text"
ref={inputRef} ref={inputRef}
style={{ style={{
...@@ -429,6 +439,7 @@ export const Input: FunctionComponent< ...@@ -429,6 +439,7 @@ export const Input: FunctionComponent<
/> />
) : ( ) : (
<input <input
name={name}
className="input-text" className="input-text"
ref={inputRef} ref={inputRef}
style={{ textAlign: inputAlign }} style={{ textAlign: inputAlign }}
...@@ -504,7 +515,7 @@ export const Input: FunctionComponent< ...@@ -504,7 +515,7 @@ export const Input: FunctionComponent<
)} )}
</div> </div>
) )
} })
Input.defaultProps = defaultProps Input.defaultProps = defaultProps
Input.displayName = 'NutInput' Input.displayName = 'NutInput'
...@@ -8,6 +8,8 @@ import React, { ...@@ -8,6 +8,8 @@ import React, {
useLayoutEffect, useLayoutEffect,
MouseEvent, MouseEvent,
HTMLInputTypeAttribute, HTMLInputTypeAttribute,
forwardRef,
useImperativeHandle,
} from 'react' } from 'react'
import { formatNumber } from './util' import { formatNumber } from './util'
...@@ -30,6 +32,7 @@ export type ConfirmTextType = 'send' | 'search' | 'next' | 'go' | 'done' ...@@ -30,6 +32,7 @@ export type ConfirmTextType = 'send' | 'search' | 'next' | 'go' | 'done'
export interface InputProps extends IComponent { export interface InputProps extends IComponent {
type: InputType type: InputType
name: string
defaultValue: any defaultValue: any
placeholder: string placeholder: string
label: string label: string
...@@ -86,6 +89,7 @@ export interface InputProps extends IComponent { ...@@ -86,6 +89,7 @@ export interface InputProps extends IComponent {
const defaultProps = { const defaultProps = {
...ComponentDefaults, ...ComponentDefaults,
type: 'text', type: 'text',
name: '',
defaultValue: '', defaultValue: '',
placeholder: '', placeholder: '',
label: '', label: '',
...@@ -125,11 +129,12 @@ export const Input: FunctionComponent< ...@@ -125,11 +129,12 @@ export const Input: FunctionComponent<
React.HTMLAttributes<HTMLDivElement>, React.HTMLAttributes<HTMLDivElement>,
'onChange' | 'onBlur' | 'onFocus' | 'onClick' 'onChange' | 'onBlur' | 'onFocus' | 'onClick'
> >
> = (props) => { > = forwardRef((props, ref) => {
const { locale } = useConfig() const { locale } = useConfig()
const { const {
children, children,
type, type,
name,
defaultValue, defaultValue,
placeholder, placeholder,
label, label,
...@@ -218,6 +223,10 @@ export const Input: FunctionComponent< ...@@ -218,6 +223,10 @@ export const Input: FunctionComponent<
} }
}, [inputValue]) }, [inputValue])
useImperativeHandle(ref, () => {
return inputRef.current
})
const inputClass = useCallback(() => { const inputClass = useCallback(() => {
const prefixCls = 'nut-input' const prefixCls = 'nut-input'
return [ return [
...@@ -405,6 +414,7 @@ export const Input: FunctionComponent< ...@@ -405,6 +414,7 @@ export const Input: FunctionComponent<
> >
{type === 'textarea' ? ( {type === 'textarea' ? (
<textarea <textarea
name={name}
className="input-text" className="input-text"
ref={inputRef} ref={inputRef}
style={{ style={{
...@@ -429,6 +439,7 @@ export const Input: FunctionComponent< ...@@ -429,6 +439,7 @@ export const Input: FunctionComponent<
/> />
) : ( ) : (
<input <input
name={name}
className="input-text" className="input-text"
ref={inputRef} ref={inputRef}
style={{ textAlign: inputAlign }} style={{ textAlign: inputAlign }}
...@@ -504,7 +515,7 @@ export const Input: FunctionComponent< ...@@ -504,7 +515,7 @@ export const Input: FunctionComponent<
)} )}
</div> </div>
) )
} })
Input.defaultProps = defaultProps Input.defaultProps = defaultProps
Input.displayName = 'NutInput' Input.displayName = 'NutInput'
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册