index.md 17 KB


localeCode: zh-CN order: 49 category: 输入类 title: TagInput 标签输入框 icon: doc-tagInput

brief: 标签输入框能够将输入的内容生成标签。

代码演示

如何引入

import { TagInput } from '@douyinfe/semi-ui';

基本演示

敲击回车键后,输入内容将成为标签。标签内容如果为空串或者纯空格时,则会被过滤。

import React from 'react';
import { TagInput } from '@douyinfe/semi-ui';

() => (
    <TagInput
        defaultValue={['抖音', '火山', '西瓜视频']}
        placeholder='请输入...'
        onChange={v => console.log(v)}
    />
);

批量添加

可以使用 separator 设置分隔符,来实现批量输入,它的默认值为英文逗号。支持多个分隔符以 string[] 格式传入。

import React from 'react';
import { TagInput } from '@douyinfe/semi-ui';

() => (
    <>
        <TagInput 
            separator='-' 
            placeholder='使用 - 进行批量输入'
            onChange={v => console.log(v)}
        />
        <br/><br/>
        <TagInput 
            separator={['-', '/', '|', '++']}
            placeholder='支持多个分隔符进行批量输入'
            onChange={v => console.log(v)}
        />
    </>
);

批量删除

可使用 showClear 设置是否支持一键删除所有标签和输入框内容。

import React from 'react';
import { TagInput } from '@douyinfe/semi-ui';

() => (
    <TagInput 
        showClear 
        defaultValue={['抖音', '火山']} 
        placeholder='请输入...'
        onChange={v => console.log(v)}
    />
);

禁用

import React from 'react';
import { TagInput } from '@douyinfe/semi-ui';

() => (
    <TagInput 
        disabled 
        showClear 
        defaultValue={['抖音', '火山', '西瓜视频']} 
        placeholder='请输入...'
    />
);

尺寸大小

通过 size 控制标签输入框的大小尺寸,可选: smalldefaultlarge

import React from 'react';
import { TagInput } from '@douyinfe/semi-ui';

() => (
    <>
        <TagInput size='small' placeholder='small'/>
        <br/><br/>
        <TagInput placeholder='default'/>
        <br/><br/>
        <TagInput size='large' placeholder='large'/>
    </>
);

不同校验状态样式

可以使用 validateStatus 设置不同校验状态的样式,它仅影响背景颜色等样式表现,可选值: defaultwarningerror

import React from 'react';
import { TagInput } from '@douyinfe/semi-ui';

() => (
    <>
        <TagInput placeholder='default'/>
        <br/><br/>
        <TagInput placeholder='warning' validateStatus='warning'/>
        <br/><br/>
        <TagInput placeholder='error' validateStatus='error'/>
    </>
);

前缀 / 后缀

可以通过 prefix 传入输入框前缀,通过 suffix 传入输入框后缀,可以为文本或者 ReactNode。
prefixsuffix 传入的内容为 string 或者 Icon 时,会自动带上左右间隔;若为自定义 ReactNode,则左右间隔为 0,如需可以在你传入的 ReactNode中自行设置。

import React from 'react';
import { TagInput } from '@douyinfe/semi-ui';
import { IconVigoLogo, IconGift } from '@douyinfe/semi-icons';

() => (
    <>
        <TagInput prefix={<IconVigoLogo />} />
        <br/><br/>
        <TagInput prefix="Prefix" />
        <br/><br/>
        <TagInput suffix={<IconGift />} />
        <br/><br/>
        <TagInput suffix="Suffix" />
    </>
);

失焦后自动创建标签

可使用 addOnBlur,设置是否在 blur 事件触发时,将当前 input 的值自动创建成 tag。

import React from 'react';
import { TagInput } from '@douyinfe/semi-ui';

() => (
    <TagInput
        defaultValue={['抖音', '火山', '西瓜视频']}
        addOnBlur={true}
        placeholder='请输入...'
        onChange={v => console.log(v)}
    />
);

过滤重复标签

可使用 allowDuplicates,设置是否允许创建相同 tag,默认为 true。

import React from 'react';
import { TagInput } from '@douyinfe/semi-ui';

() => (
    <TagInput
        defaultValue={['抖音', '火山', '西瓜视频']}
        allowDuplicates={false}
        placeholder='请输入...'
        onChange={v => console.log(v)}
    />
);

输入限制

可使用 max 限制输入的标签数量,超出后将不允许再输入,并且触发 onExceed() 回调。

可使用 maxLength 限制单个标签的最大长度,超出后将不允许再输入,并且触发 onInputExceed() 回调。

import React from 'react';
import { TagInput } from '@douyinfe/semi-ui';

() => (
    <>
        <TagInput 
            max={3} 
            placeholder='最多输入3条标签..' 
            onChange={v => console.log(v)}
            onExceed={v => {
                Toast.warning('超过 max');
                console.log(v);
            }}
        />
        <TagInput 
            maxLength={5} 
            placeholder='单个标签长度不超过5...'  
            style={{ marginTop: 12 }}
            onChange={v => console.log(v)}
            onInputExceed={v => {
                Toast.warning('超过 maxLength');
                console.log(v);
            }} 
        />
    </>
);

限制标签展示数量

利用 maxTagCount 可以限制展示的标签数量,超出部分将以 +N 的方式展示。使用 showRestTagsPopover 可以设置在超出 maxTagCount 后,hover +N 是否显示 Popover,并且可以在 restTagsPopoverProps 属性中配置 Popover

import React from 'react';
import { TagInput } from '@douyinfe/semi-ui';

() => (
    <TagInput 
        maxTagCount={2}
        showRestTagsPopover={true}
        restTagsPopoverProps={{ position: 'top' }}
        defaultValue={['抖音', '火山', '西瓜视频']}
        onChange={v => console.log(v)}
    />
);

标签受控

可使用 value 设置标签内容,并配合 onChange 实现标签内容受控。

import React, { useState } from 'react';
import { TagInput } from '@douyinfe/semi-ui';

function TagInputDemo() {
    const [value, setValue] = useState(['抖音']);
    const handleChange = v => setValue(v);
    return <TagInput value={value} onChange={handleChange} />;
}

输入受控

可使用 inputValue 设置输入框内容,并配合 onInputChange 实现输入内容受控。

import React, { useState } from 'react';
import { TagInput } from '@douyinfe/semi-ui';

function TagInputDemo() {
    const [value, setValue] = useState('abc');
    const handleInputChange = (v, e) => setValue(v);
    return <TagInput inputValue={value} onInputChange={handleInputChange} />;
}

回调

import React from 'react';
import { TagInput } from '@douyinfe/semi-ui';

() => (
    <TagInput 
        defaultValue={['抖音']} 
        placeholder='请输入...'
        showClear 
        onFocus={e => {console.log(`onFocus`);}} 
        onBlur={e => {console.log(`onBlur`);}} 
        onChange={tag => {console.log(`onChange,当前标签数组:${tag}`);}} 
        onAdd={tag => {console.log(`onAdd,新增:${tag}`);}} 
        onRemove={(v, i) => {console.log(`onRemove,移除:${v}, 序号:${i}`);}} 
        onInputChange={(input, e) => {console.log(`onInputChange,当前输入内容:${input}`);}} 
    />
);

焦点管理

可以使用 blur()focus() 方法对焦点进行管理。

import React, { useRef } from 'react';
import { TagInput, Button } from '@douyinfe/semi-ui';

function TagInputDemo() {
    const ref = useRef();
    const handleTagInputFocus = () => {
        ref.current && ref.current.focus();
    };

    return (
        <>
            <TagInput defaultValue={['抖音', '火山']} ref={ref} />
            <Button style={{ marginTop: 10 }} onClick={handleTagInputFocus}>
                点击按钮聚焦
            </Button>
        </>
    );
}

自定义标签渲染

可以使用 renderTagItem 自定义标签渲染。 renderTagItem(value: string, index: number, onClose: function ) => React.ReactNode 第三个参数 onClose 于 2.23.0 版本开始提供。

import React, { useMemo, useState } from 'react';
import { TagInput, Avatar } from '@douyinfe/semi-ui';
import { IconClose } from '@douyinfe/semi-ui-icons';

function CustomRender() {
    const [value, setValue] = useState(['夏可漫']);
    const list = useMemo(() => ([
        { "name": "夏可漫", "avatar": "https://sf6-cdn-tos.douyinstatic.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/root-web-sites/avatarDemo.jpeg" },
        { "name": "申悦", "avatar": "https://sf6-cdn-tos.douyinstatic.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/root-web-sites/bf8647bffab13c38772c9ff94bf91a9d.jpg" },
        { "name": "曲晨一", "avatar": "https://sf6-cdn-tos.douyinstatic.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/root-web-sites/dbf7351bb779433d17c4f50478cf42f7.jpg" },
        { "name": "文嘉茂", "avatar": "https://sf6-cdn-tos.douyinstatic.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/root-web-sites/7abf810ff060ac3387bd027ead92c4e0.jpg" },
    ]), []);
    const mapList = useMemo(() => new Map(list.map(item => [item.name, item])), [list]);

    const renderTagItem = (value, index, onClose) => {
        const data = mapList.get(value);
        return (
            <div
                key={index}
                style={{ 
                    backgroundColor: 'var(--semi-color-info-light-default)',
                    padding: '4px 8px',
                    borderRadius: 12,
                    display: 'flex', alignItems: 'center', fontSize: 14,
                    marginRight: 10 
                }}
            >
                <Avatar
                    alt='avatar'
                    src={data ? data.avatar : 'https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/root-web-sites/dy.png'}
                    size="extra-small"
                />
                <span style={{ marginLeft: 8 }}>
                    {`${value}@semi.com`}
                </span>
                <IconClose style={{ paddingLeft: 4, color: 'var( --semi-color-text-3)' }} size="small" onClick={onClose} />
            </div>
        );
    };

    return (
        <TagInput
            value={value}
            onChange={setValue}
            renderTagItem={renderTagItem}
        />
    );
}

拖拽排序

draggable设为 true,开启拖拽排序功能。v2.17.0 后支持。拖拽排序下不允许添加相同 Tag, 因此需要将 allowDuplicates 设置为 false。 拖拽功能开启后,点击 TagInput,Tag 可拖拽。点击 TagInput 外任意区域,Tag 不可拖拽。

import React from 'react';
import { TagInput } from '@douyinfe/semi-ui';

() => (
    <TagInput
        draggable
        allowDuplicates={false}
        defaultValue={['抖音', '火山', '西瓜视频']}
        placeholder='请输入...'
        onChange={v => console.log(v)}
    />
);

API 参考

Methods

绑定在组件实例上的方法,可以通过 ref 调用实现某些特殊交互

属性 说明 类型 默认值 版本
addOnBlur 是否在 blur 事件触发时,将当前 input 的值自动创建成 tag boolean false -
allowDuplicates 是否允许添加相同 tag boolean true -
autoFocus 初始渲染时是否自动 focus boolean false -
className 样式类名 string - -
defaultValue 初始标签 string[] - -
disabled 是否禁用 boolean false -
inputValue 当前输入框,配合 onInputChange 实现受控 string - -
maxLength 单个标签的最大长度 number - -
max 允许标签的最大数量 number - -
maxTagCount 标签的最大展示数量,超出后将以 +N 形式展示 number - -
showRestTagsPopover 当超过 maxTagCount,hover 到 +N 时,是否通过 Popover 显示剩余内容 boolean true -
restTagsPopoverProps Popover 的配置属性,可以控制弹出方向、zIndex、trigger等,具体参考Popover PopoverProps {} -
showContentTooltip 当标签长度过长发生截断时,hover 标签的时候,是否通过 Tooltip 显示全部内容, 支持 Tooltip|Popover;opts,其他需要透传给浮层组件的属性 boolean|{type: 'tooltip'|'popover', opts: object} true -
placeholder 占位默认值 string - -
prefix 前缀标签 ReactNode - -
preventScroll 指示浏览器是否应滚动文档以显示新聚焦的元素,作用于组件内的 focus 方法 boolean
renderTagItem 自定义标签渲染, 参数 onClose 于版本2.23.0版本提供 - -
separator 设置批量输入时的分隔符 string|string[] , -
showClear 是否支持一键删除所有标签和输入内容 boolean false -
size 设置输入框尺寸,可选: smalllargedefault string default -
split 自定义分隔符处理函数 (value: string, separator: string) => string[] - 2.90.0
style 内联样式 React.CSSProperties - -
suffix 后缀标签 ReactNode - -
validateStatus 设置校验状态样式,可选: defaultwarningerror string default -
value 当前标签,配合 onChange 实现受控 string[] | undefined - -
draggable 设置是否可拖拽 boolean false 2.17.0
expandRestTagsOnClick 在不可拖拽的情况下,在 TagInput 被点击后是否展开多余的 Tag boolean true 2.17.0
onAdd 添加标签时的回调 (addedValue: string[]) => void - -
onBlur 输入框失去焦点时的回调 (e:React.MouseEvent) => void - -
onChange 标签变化时的回调 (value:string[]) => void - -
onExceed 超过 max 时的回调 (value:string[]) => void - -
onFocus 输入框获取焦点时的回调 (e:React.MouseEvent) => void - -
onInputChange 输入框内容变化时的回调 (value:string,e: React.KeyboardEvent) => void) - -
onInputExceed 超过 maxLength 时的回调 (value:string) => void - -
onKeyDown keydown 回调 (e: React.KeyboardEvent) => void - 2.1.0
onRemove 移除标签时的回调 (removedValue: string, idx: number) => void - -
名称 描述 版本
blur() 移出焦点 -
focus() 获取焦点 -

Accessibility

ARIA

  • TagInput 支持传入 aria-label 来表示该 TagInput 作用;
  • TagInput 会依据 disabled 及 validateStatus props 来分别设置 aria-disabledaria-invalid
  • TagInput 的输入框和清空按钮均具有 aria-label 来表明元素作用。

设计变量