react+antd Input回车输入生成tag组件

实现的组件样式

focus效果

 代码:

import React from 'react'
import { Input, Tag, Tooltip } from 'antd';
import { CloseCircleFilled } from '@ant-design/icons'
import isEqual from 'lodash/isEqual'
import './index.less'

interface ITagState {
  tags: string[]
  inputValue: string
}

interface ITagProps {
  value?: []
  onChange?: (value) => void
}

class EditableTagGroup extends React.Component<ITagProps, ITagState> {
  constructor(props) {
    super(props)
    this.state = {
      tags: props.value || [],
      inputValue: ''
    }
  }
  input: HTMLElement
  handleClose = removedTag => {
    const tags = this.state.tags.filter(tag => tag !== removedTag);
    this.setState({ tags });
  };
  refDom = () => {
    return <>
      {this.state.tags.map((tag, index) => {
        const isLongTag = tag.length > 20
        const tagElem = <Tag
          key={index}
          closable={true}
          onClose={() => this.handleClose(tag)}
          closeIcon={<CloseCircleFilled className='close-icon' />}
        >
          {isLongTag ? `${tag.slice(0, 20)}...` : tag}
        </Tag>

        return isLongTag ? (
          <Tooltip title={tag} key={tag}>
            {tagElem}
          </Tooltip>
        ) : (
          tagElem
        );
      })}
    </>
  }
  inputChange = (e) => {
    this.setState({
      inputValue: e.target.value
    })
  }
  addTag = (e) => {
    const value = e.target.value
    if (value) {
      this.setState({
        tags: [
          ...this.state.tags,
          value
        ],
        inputValue: ''
      })
    }
  }
  componentDidUpdate(prevProps, prevState) {
    if (!isEqual(prevProps.value, this.props.value)) {
      this.setState({
        tags: this.props.value
      })
    }
    if (!isEqual(prevState.tags, this.state.tags)) {
      console.log(prevState.tags, this.state.tags);
      if (this.props.onChange) {
        this.props.onChange(this.state.tags)
      }
    }
  }
  saveInputRef = input => {
    this.input = input;
  };
  clickEdit = () => {
    this.input.focus()
  }
  render() {
    const { inputValue } = this.state
    return (
      <div className='editable' onClick={this.clickEdit}>
        <div className='show'>{this.refDom()}</div>
        <Input className='input' ref={this.saveInputRef} placeholder='在此输入,回车添加' onPressEnter={this.addTag} value={inputValue} onChange={this.inputChange} />
      </div>
    )
  }
}

export default EditableTagGroup
.editable {
  height: 80px;
  border-radius: 2px;
  background-color: rgba(255, 255, 255, 1);
  border: 1px solid #d9d9d9;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  &:focus-within,
  &:hover {
    border-color: rgba(22, 119, 254, 1);
    box-shadow: 0 0 4px 0 rgba(10, 42, 97, 0.2);
  }
  .ant-input {
    border: none;
    height: 32px;
    &:hover,
    &:focus {
      box-shadow: none;
      border: none;
    }
  }
  .show {
    flex: 1;
    min-height: '47px';
    overflow: auto;
    padding: 0 5px;
    .ant-tag {
      color: #5a5e66;
      padding: 2px 8px;
      font-size: 12px;
      border: none;
      border-radius: 3px;
      background-color: rgba(240, 242, 245, 1);
      .close-icon {
        color: rgba(192, 196, 204, 1);
        margin-left: 2px;
        font-size: 12px;
      }
    }
  }
}

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值