我的任务是在ReactJs中创建一个自定义的选择,这样当它被用在网站上时,在所有的浏览器中看起来都是一样的。值得注意的是,内置的浏览器选择元素的设计在不同的浏览器中是不一样的。
下面我将带你了解我如何使用ReactJs和Styled组件开发一个简单的自定义选择元素。请欣赏
首先,我们需要一个开发环境。我通常使用 codesand box 来完成这样的工作。请随意在那里创建一个ReactJs环境,或者你可以直接在你的本地机器上使用create-react-app。
让我们马上进入正题。
我们将使用styled-components编写我们的CSS规则/样式。你可以用下面的命令来安装它。
npm install --save styled-components
或
yarn add styled-components
结构
现在我们已经完成了自己的依赖性安装,让我们看看下面的选择/下拉自定义元素的结构。
使用从styled-components导入的styled,我们将对不同的jsx元素进行样式化,如div ul和li元素。它们将反过来作为React元素被返回。
DropDownContainer是整个选择的伞状div容器,DropDownHeader是显示当前选择的选项的元素,DropDownListContainer是包含无序列表DropDownList的div,它有无序元素ListItem作为其子元素。那么芒果、苹果和橙子就是我们当前的选择选项。下面是上述结构在Chrome浏览器中的视觉表现。

样式/设计
现在我们已经完成了结构的设计,让我们为我们的元素添加一些样式。下面是应用这些样式后的自定义选择的图片。

下面是带有样式的代码和每个元素的相应解释。
我们将<div className="App">改为<Main>,并添加了背景和高度,如上面GitHub gist中所示。由于我们的列表的背景是白色的,所以我们改变了主背景,以便我们可以清楚地看到我们的选择。
我们为DropDownContainer设计了一个宽度,也就是自定义选择的宽度,以及一个边距,为了本教程的目的,这个边距只是自定义选择的中心。
DropDownContainer的样式有点不言自明,但重要的是要注意,我们添加了一个盒状阴影,以便添加阴影和底边距,这样标题和项目列表之间就有了分隔。
在DropDownList样式中,我想强调下面这个部分。
&:first-child {
padding-top: 0.8em;
}
本质上,它为DropDownList(ul)的第一个子项(即本例中的第一个ListItem(li)Mangoes)添加了一个顶部填充。
行为
我们现在有了自定义选择的基础设计,现在让我们继续添加所需的行为,当点击标题时,会显示或隐藏列表,如下所示。

我们使用React Hooks来创建一个isOpen布尔值,我们将用它来切换列表的可见性,如下图所示。
const [isOpen, setIsOpen] = useState(false);
然后添加一个点击处理程序,负责将布尔值切换为真或假,如下所示。
const toggling = () => setIsOpen(!isOpen);
然后,点击监听器被连接到DropDownHeader,这样当用户点击时,isOpen状态变量就会被切换为false或true。
<DropDownHeader onClick={toggling}>Mangoes</DropDownHeader>
最后,isOpen状态变量被用来显示或隐藏DropDownListContainer,如下面的代码片段所示。
{isOpen && (
<DropDownListContainer>
<DropDownList>
<ListItem>Mangoes</ListItem>
<ListItem>Apples</ListItem>
<ListItem>Oranges</ListItem>
</DropDownList>
</DropDownListContainer>
)}
这里是到此为止的所有代码。
选定选项
为了从自定义选择中获取和存储所选选项,我们使用React钩子添加一个新的状态变量,如下图所示。
const [selectedOption, setSelectedOption] = useState(null);
当一个选项被点击时,我们需要一个点击处理程序,该程序将被调用,并带有所选的选项,这样我们就可以把它添加到selectedOption状态变量中,也可能为了本教程的目的把它记录到控制台。下面是点击处理程序的代码片段。
const onOptionClicked = value => () => {
setSelectedOption(value);
setIsOpen(false);
console.log(selectedOption);
};
值参数是被选中的选项,需要注意的是,当一个项目被点击时,我们还必须隐藏列表,这就是为什么我们把setIsOpen设置为false,最后把选中的选项/值记录下来。
列表项的值也被移到一个数组中,这样我们只需映射它们并创建各自的ListItem,如下所示。
const options = ["Mangoes", "Apples", "Oranges"];
下面是选项的映射。
<DropDownList>
{options.map(option => (
<ListItem onClick={onOptionClicked(option)} key={Math.random()}>
{option}
</ListItem>
))}
</DropDownList>
一个点击处理程序被添加到每个ListItem中,这样当用户点击一个项目时,它的值就会被传递到函数中。还添加了一个唯一的键,这样React就能跟踪每个ListItem。