我需要稍微自定义一个反应选择下拉列表。 它是多项选择,我的目标是当用户选择多个选项时,所选选项仅占用框中可用的水平空间。 溢出应该用椭圆处理。
默认行为 - 溢出项目换行到下一行并使框高度增长:
所需的行为 - 自定义渲染,带椭圆
我实现此目的的策略是在选择中使用自定义组件
ValueContainer
:
const ValueContainer = (props) => (
<div
{...props.innerProps}
style={{
whiteSpace: "nowrap",
overflow: "hidden",
textOverflow: "ellipsis",
}}
>
{props.selectProps?.value?.map((p) => p.label).join(", ")}
</div>
);
const MyComponent = () => {
// state logic here
return (
<Select
options={options}
value={value}
isMulti
onChange={(value) => setValue(value)}
components={{ ValueContainer }}
/>
);
这确实有效,正如您在此代码和框中看到的那样。
但是,我似乎失去了默认行为。 在沙箱的左侧示例中(默认如上所示),当您单击下拉列表的任何部分(现有选择、空白区域、下拉指示器等)时,下拉列表将打开。 这就是我想要的行为。 在我的自定义示例中,单击列表不会打开下拉菜单 - 您必须专门单击微小的下拉箭头才能将其打开。 同样,当其打开时,默认行为有一个单击离开处理程序,单击屏幕上的任意位置都会关闭菜单。 此自定义
ValueContainer
组件也会丢失该行为。
如何在使用自定义
ValueContainer
组件时保持此自定义打开/关闭单击行为? 正如文档中所述,innerRef
的道具上似乎没有 ValueContainer
。 这些道具中是否有我缺少的 setOpen
道具? 有没有更好的方法可以达到我想要的效果?
由于您为 ValueContainer 使用自定义组件并且不再返回其默认子组件,因此您不再渲染输入,因此无法访问其模糊事件(有关更多详细信息,请参阅此答案)
但是,在您的情况下,您不必使用自定义 ValueContainer 组件。 一种可能的解决方法是使用自定义多值组件来连接所有选定的值。
const MultiValue = (props) => {
const selectedValues = props.getValue();
// Render only the first value
if (props.index > 0) return null;
// Instead of the first value, display a string with all the concatenated values
const displayedValue = selectedValues.map((value) => value.label).join(",");
return (
<div
style={{
whiteSpace: "nowrap",
overflow: "hidden",
textOverflow: "ellipsis",
}}
{...props.innerProps}
>
{displayedValue}
</div>
);
};
您还需要对值容器进行细微的样式调整
<Select
options={this.options}
value={this.state.value2}
isMulti
onChange={(value) => this.setState({ value2: value })}
defaultValue={{ label: 2002, value: 2002 }}
components={{ MultiValue }}
styles={{
valueContainer: (base) => ({ ...base, flexWrap: "nowrap" }),
}}
/>
一个可以说更好的解决方案是修改自定义 MultiValue 组件来为每个值呈现一个字符串,但您必须以其他方式实现省略号溢出。