我使用styled-components
和flexbox开发了以下React DropdownList组件:
import React from "react";
import PropTypes from "prop-types";
import styled from "styled-components";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { faCaretDown } from "@fortawesome/free-solid-svg-icons";
const options = [
{
key: "opt1",
value: "Option 1",
},
{
key: "opt2",
value: "Option 2",
},
{
key: "opt3",
value: "Option 3",
},
{
key: "opt4",
value: "Option 4",
},
{
key: "opt5",
value: "Option 5",
},
{
key: "opt6",
value: "Option 6",
},
{
key: "opt7",
value: "Option 7",
},
];
const DropdownListContainer = styled.div`
position: relative;
display: inline-block;
${(props) =>
props.disabled &&
`
opacity: 0.6;
`}
`;
const DropdownListButton = styled.button`
display: flex;
align-items: flex-start;
width: 100%;
background-color: white;
padding: ${(props) =>
props.collapse ? "7px 8px 7px 8px" : "8px 8px 8px 8px"};
border: 1px solid black;
border-radius: 4px;
cursor: pointer;
overflow: hidden;
}`;
const DropdownListButtonTitle = styled.div`
display: flex;
justify-content: space-between;
align-items: center;
width: 100%;
}`;
const DropdownListContentDiv = styled.div`
display: ${(props) => (props.collapsed ? "none" : "absolute")};
min-width: 160px;
position: relative;
background-color: white;
border: 1px solid #fefefe;
min-width: 160px;
box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2);
z-index: 10;
}`;
const OptionDiv = styled.div`
width: 100%;
padding: 4px 0px 4px 4px;
overflow: hidden;
&:hover {
background-color: #020202;
color: white;
}
`;
class DropdownList extends React.Component {
static propTypes = {
onChange: PropTypes.func,
onDropdownListClick: PropTypes.func,
value: PropTypes.any,
options: PropTypes.array,
disabled: PropTypes.bool,
large: PropTypes.bool,
};
state = {
collapsed: true,
};
handleButtonClick = () => {
this.setState({
collapsed: !this.state.collapsed,
});
};
handleSelect = (id) => {
if (this.props.onChange) this.props.onChange(id);
this.setState({
collapsed: true,
});
};
render = () => {
let { value, disabled, large, readOnly } = this.props;
// let { options } = this.props; // Using hardcoded options for testing
let { collapsed } = this.state;
let optionsList = [];
let val = null;
if (options && options.length > 0) {
options.forEach((option) => {
let content = option.value;
optionsList.push(
<OptionDiv
key={option.key}
onClick={() => this.handleSelect(option.key)}
large={large}
>
{content}
</OptionDiv>
);
if (value === option.key) val = option.value;
});
}
if (!val && options && options.length > 0) val = options[0].value;
let buttonContent = (
<DropdownListButtonTitle>
<div>{val}</div>
<div>
<FontAwesomeIcon icon="faCaretDown" size="small" />
</div>
</DropdownListButtonTitle>
);
return (
<DropdownListContainer disabled={disabled}>
<DropdownListButton
onClick={this.handleButtonClick}
disabled={readOnly}
>
{buttonContent}
</DropdownListButton>
<DropdownListContentDiv collapsed={collapsed}>
{optionsList}
</DropdownListContentDiv>
</DropdownListContainer>
);
};
}
export default DropdownList;
它运行良好,除了造型问题。如果我在内容内部使用,当我打开菜单时,它会向下移动所有内容。当我在视图屏幕的末尾使用它时,也会发生同样的行为。它会增加视图高度并弹出滚动条。
我确实希望它";浮动";在内容上方,显示其上方的内容。在屏幕的边缘,我希望它朝相反的方向打开(如果我在屏幕底部,则向上;如果我在最右侧,则向左(。
DropdownListContentDiv不应该得到显示"none";或";"绝对";,它应该得到显示";none";或";块";。之后,该内容的位置不是";相对";,但是";"绝对";,像这样:
const DropdownListContentDiv = styled.div`
display: ${(props) => (props.collapsed ? "none" : "block")};
min-width: 160px;
position: absolute;
background-color: white;
border: 1px solid #fefefe;
min-width: 160px;
box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2);
z-index: 10;
}`;