在React中自定义选择/下拉的方法

347 阅读4分钟

我的任务是在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。