javascript 如何使用React像Google文档一样进行分页

gzjq41n4  于 2023-06-28  发布在  Java
关注(0)|答案(2)|浏览(115)

bounty还有2天到期。此问题的答案有资格获得+50声望奖励。Sivanesh S正在寻找一个答案从一个有信誉的来源

在Google Docs中,如果您创建文档。你将从第一页开始写。如果页面内容已满,则自动创建第2页,其余内容转到第2页,依此类推。如果您从第1页删除了一些行,则第2页的内容(如果有的话)将被移动到第1页的底部。
因此,在我的场景中,我有一些表示组件(大约10个),它们由一个表单填充。考虑左窗格有一个表单,更新它们会在右窗格上显示类似于文档的UI的实时预览。
我尝试在react应用程序中使用一些方法(如insertBefore)直接操作DOM。我读到直接在React应用程序上进行DOM操作容易出错,不建议这样做。是否有其他模式或方法来实现此用例?

yeotifhr

yeotifhr1#

  • 是的,除了直接操作DOM或通过DS管理分页之外,您还可以考虑使用专门为文档编辑和分页设计的库或框架。
  • 使用Draft.js
55ooxyrt

55ooxyrt2#

我想说的是,唯一能解决你的问题的方法是用useLayoutEffect来测量内容的大小,然后将所说的内容“分割”成页面。
(This是因为我假设你不知道列表中每个项目的大小-如果你知道的话会更简单!).
我会从一个useComponentSize钩子开始,它看起来像这样:

// Adapted from: https://stackoverflow.com/a/57272554/6595024

const useComponentSize = () => {
  const informParentOfHeightChange = useContext<(h: number) => void>(
    UpdateParentAboutMyHeight
  );
  const targetRef = useRef();

  useLayoutEffect(() => {
    if (targetRef.current) {
      informParentOfHeightChange(targetRef.current.offsetHeight);
    }

    return () => informParentOfHeightChange(0);
  }, [informParentOfHeightChange]);

  return targetRef;
};

const UpdateParentAboutMyHeight = /* Left as an exercise to the reader */

注意:我的实现是相当'基本'的;你可能会想要useTransition或其他类型的反跳效果,这样你的UI就不会慢到爬行
使用这个钩子,子节点可以在它的高度改变时通知父节点。下面是一个例子:

const Comp = () => {
  const targetRef = useComponentSize();

  return <div ref={targetRef}>{/* etc */}</div>;
};

因此,您需要做的“所有”就是创建一个父组件,跟踪它的所有Comp子组件的高度。
下面是一些(低效的)伪代码,可以帮助你理解:

const UpdateParentAboutMyHeightProvider = /* Left as an exercise to the reader */

const HEIGHT_PER_PAGE = 1000;

const PageLayout = ({ items_to_render }: { items_to_render: Comp[] }) => {
  const [items, setItems] = useState<{ height: number }[]>([]);

  let curHeight = 0;
  let curPage = 0;
  const pages = items_to_render.reduce((pageList, item, index) => {
    if (curHeight >= HEIGHT_PER_PAGE) {
      // Create a new page!
      pageList.push([item]);
      curHeight = items[index].height;
      curPage += 1;
      return pageList;
    }
    // Add to existing page!
    curHeight += items[index].height;
    pageList[curPage].push(item);
    return pageList;
  }, [] as Array<Array<Comp>>);

  return (
    <UpdateParentAboutMyHeightProvider value={setItems}>
      {pages.map((page, number) => (
        <Page number={number + 1} key={number}>{page.map((item) => item)}</Page>
      ))}
    </UpdateParentAboutMyHeightProvider>
  );
};

我将重复我在这里写的实现是非常基本和低效的;当页面大于最大大小时的逻辑也是不充分的[1]
希望它能帮你找到正确的方向。
[1]你必须从数组中弹出项目,直到它低于最大高度。我保持简单是为了可读性,因为我不知道你的特定用例,

相关问题