1.前言
近期因公司项目需求,需要做一个多选的下拉列表。找了许多UI框架都没有找到适合的,因此决定自己封装一个并分享出来供有需求的伙伴们使用。项目需求如下图所示:
2.实现思路
最初想法是用ant-design Tag和Dropdown实现,由于Dropdown会屏蔽自定义事件而且Tag在close时会因为销毁组件而取不到目标值。因此最后使用Popover以及自己封装的TagButton组件来实现该需求。本篇文件只讲实现过程,具体的依赖安装小伙伴们可以自己百度。
3.实现代码
由于时间原因只是实现了该需求的功能,具体样式在这里就不说了,实现的组件如下图所示:
下面附上实现代码,自取所需:
index.jsx
import React, { Component } from 'react';
import { Menu, Dropdown, Icon, Tag, Popover, Button } from 'antd';
import TagButton from './tag'
require('./index.less')
export default class SourceDemo extends Component {
/***********************/
/*父组件传值接口sectList*/
/**********************/
state = {
selectList:[],
tagList:[],
selectedKeys: []
}
constructor(props) {
super(props)
}
componentDidMount() {
this.setState({selectList: this.props.sectList});
}
handleButtonSelect = (e) => {
this.setState({selectedKeys: e.selectedKeys})
this.state.tagList.push(e.item.props.value)
}
handleButtonDeSelect = (e) => {
let delValue = this.state.tagList
delValue.splice(delValue.findIndex(item => item.id == e.key), 1)
this.setState({selectedKeys: e.selectedKeys, tagList: delValue})
}
handleShow = (itemId) => {
let deValue = this.state.tagList
let selKeys = this.state.selectedKeys
deValue.splice(deValue.findIndex(item => item.id == itemId), 1)
selKeys.splice(selKeys.findIndex(item => item.id == itemId), 1)
this.setState({tagList: deValue, selectedKeys:selKeys})
}
render() {
const menu = (
<Menu selectedKeys={this.state.selectedKeys} multiple={true} onSelect={this.handleButtonSelect} onDeselect={this.handleButtonDeSelect}>
{
this.state.selectList.map((item,index) => (
<Menu.Item value={item} key={item.id}>
<a>{item.title}</a>
</Menu.Item>
))
}
</Menu>
);
return (
<div className="multi-select-box">
{
this.state.tagList.map((item, index) => (
<TagButton key={item.id} itemTitle={item.title} itemId={item.id} handleShow={this.handleShow}></TagButton>
))
}
<Popover overlayClassName='multi-select-popover' placement="bottomLeft" content={menu} trigger="click">
<Button>BL</Button>
</Popover>
</div>
)
}
}import React, { Component } from 'react'
require('./tag.less')
export default class CustomRemoteSelect extends Component {
state = {
}
constructor(props) {
super(props)
}
render() {
return (
<div className="tag-wrapper">
{this.props.itemTitle}
<i className="anticon" onClick={() => this.props.handleShow(this.props.itemId)}></i>
</div>
)
}
}
复制代码
tag.jsx
import React, { Component } from 'react'
require('./tag.less')
export default class CustomRemoteSelect extends Component {
state = {
}
constructor(props) {
super(props)
}
render() {
return (
<div className="tag-wrapper">
{this.props.itemTitle}
<i className="anticon" onClick={() => this.props.handleShow(this.props.itemId)}></i>
</div>
)
}
}
复制代码
index.less
.multi-select-popover{
.ant-popover-inner-content{
padding:0;
}
}
复制代码
tag.less
.tag-wrapper{
color:rgba(0, 0, 0, 0.65);
font-family: "Monospaced Number", "Chinese Quote", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "Helvetica Neue", Helvetica, Arial, sans-serif;
box-sizing: border-box;
margin: 0;
list-style: none;
display: inline-block;
line-height: 20px;
height: 22px;
padding: 0 7px;
border-radius: 4px;
border: 1px solid #d9d9d9;
background: #fafafa;
font-size: 12px;
transition: all 0.3s cubic-bezier(0.215, 0.61, 0.355, 1);
opacity: 1;
margin-right: 8px;
cursor: pointer;
white-space: nowrap;
}
.tag-wrapper {
.anticon{
font-size:12px;
font-style: normal;
vertical-align: baseline;
text-align: center;
text-transform: none;
line-height: 1;
text-rendering: optimizeLegibility;
-webkit-font-smoothing: antialiased;
}
.anticon:before {
content: "\E633";
display: block;
font-family: "anticon" !important;
}
.anticon:hover{
color:rgba(0,0,0,0.95);
}
}
复制代码
感谢阅读本文的小伙伴们,希望本文对你们有用,有错的地方望大佬们指出,不喜勿喷谢谢!