javascript - 如何在材料 ui 自动完成中找到哪个芯片被包裹到下一行
问题描述
我有一个像这样的材料 ui 自动完成
我想计算第四个芯片包裹到下一行,以便我可以进行进一步的计算。有没有办法在 javascript/react 中使用这种材料 UI 的自动完成来做到这一点。
到目前为止,自动完成材料 ui 的文档在这种情况下没有帮助。
基本上我要做的是使数字limitTags
动态化,以便在更改自动完成的宽度时相应地设置limitTags,而不是静态数字。到目前为止,我的想法是计算每个标签的宽度,将其全部添加并与容器宽度进行比较。这已经完成但它仍然是错误的,因为正如您在所附图像中看到的那样,即使标签的组合长度小于容器宽度,limitTags 是 4,但它应该是 3,因为最后一个包裹到下一个线。现在我又被困住了。如何检测包装到下一行的第一个标签中的哪一个以计算limitTags
值
这是我到目前为止所做的
const DEFAULT_LIMIT_TAGS = -1;
const useLimitTags = (value, autoCompleteContainerRef, tagRef) => {
const [limitTags, setLimitTags] = useState(DEFAULT_LIMIT_TAGS);
const [autoCompleteContainerWidth, setAutoCompleteContainerWidth] = useState(0);
const parentNode = useRef(null);
useOnResize(autoCompleteContainerRef, setAutoCompleteContainerWidth);
useLayoutEffect(() => {
if (!parentNode.current && tagRef?.current) {
parentNode.current = tagRef.current.parentNode;
}
if (parentNode?.current) {
const children = [...parentNode.current.children];
const tags = children.slice(0, value.length);
const endAdornmentWidth = children[children.length - 2].offsetWidth;
const containerWidth = autoCompleteContainerWidth - endAdornmentWidth - 20; // 20 is the margin around the last closing icon and the dropd own icon
const tagsCombinedWidth = tags.reduce((sum, child, index, arr) => {
const tagsWidth = sum + child.offsetWidth;
if (tagsWidth > containerWidth) {
setLimitTags(index - 1);
arr.splice(0, index + 1); // break
}
return tagsWidth;
}, 0);
if (tagsCombinedWidth <= containerWidth) {
setLimitTags(DEFAULT_LIMIT_TAGS);
}
}
}, [value, autoCompleteContainerWidth, tagRef]);
return limitTags;
};
并且useOnResize
正在使用 Resize Observer API 来计算不断变化的自动完成容器的宽度
import { useEffect } from 'react';
import isFunction from 'lodash-es/isFunction';
const useOnResize = (componentRef, callback) => {
const shouldMountObserver = isFunction(callback) && componentRef?.current;
const resizeObserver =
shouldMountObserver &&
new ResizeObserver((entries) => {
for (const entry of entries) {
const { width: detectedWidth } = entry.contentRect;
callback(detectedWidth);
}
});
useEffect(() => {
const savedRef = componentRef?.current;
shouldMountObserver && resizeObserver?.observe(componentRef.current);
return () => {
if (savedRef) {
resizeObserver?.unobserve(savedRef);
}
}; // Resized observer omitted in deps array on purpose as it is not supposed to change between rerender
}, [componentRef?.current]); // eslint-disable-line react-hooks/exhaustive-deps
};
export default useOnResize;
解决方案
推荐阅读
- python - 在文本文件中搜索特定单词
- android - 您能否创建应用的免费版本和付费版本,但在用户的设备上只拥有其中一个?
- ios - 如何管理多个 AVAudioPCMBuffer 进行播放?
- javascript - 忽略javascript中的重音字母
- c++ - 可以 std::vector
::iterator 实现其 deref 运算符以返回对 _Bit_reference 的引用? - asp.net - 如何在 MVC 中将数据从 JsonResult 传递到 JQGrid?
- flask - 如何将客户端数据发送到 Windows Server 2019
- c - sizeof(char) *100 的含义
- html - 透明PNG无法显示但可下载
- java - 如何在 WebFluxConfigurer 中限制特定端点的文件部分大小