Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

react-window 源码解析--VariableSizeList #26

Open
hulin32 opened this issue Jun 11, 2019 · 0 comments
Open

react-window 源码解析--VariableSizeList #26

hulin32 opened this issue Jun 11, 2019 · 0 comments

Comments

@hulin32
Copy link
Owner

hulin32 commented Jun 11, 2019

和前面 #25 一样,最都是调用的createListComponent,不一样的地方就是调用那个函数时传入的方法,我们来一起看看。
主要的就是getStartIndexForOffsetgetStopIndexForStartIndex两个函数了

// 主要调用了findNearestItem
getStartIndexForOffset: (
  props: Props<any>,
  offset: number,
  instanceProps: InstanceProps
): number => findNearestItem(props, instanceProps, offset),
const findNearestItem = (
  props: Props<any>,
  instanceProps: InstanceProps,
  offset: number
) => {
  const { itemMetadataMap, lastMeasuredIndex } = instanceProps;
  console.log('offset', offset);
  const lastMeasuredItemOffset =
    lastMeasuredIndex > 0 ? itemMetadataMap[lastMeasuredIndex].offset : 0;

  if (lastMeasuredItemOffset >= offset) {
    // 如果查找过就直接使用二分查找
    return findNearestItemBinarySearch(
      props,
      instanceProps,
      lastMeasuredIndex,
      0,
      offset
    );
  } else {
    // 如果没有就使用指数搜索
    return findNearestItemExponentialSearch(
      props,
      instanceProps,
      Math.max(0, lastMeasuredIndex),
      offset
    );
  }
};

二分查找我猜很多人都看过了,通过查找中位数来折半查找,非常的快,来主要看看指数查找

const findNearestItemExponentialSearch = (
  props: Props<any>,
  instanceProps: InstanceProps,
  index: number,
  offset: number
): number => {
  const { itemCount } = props;
  let interval = 1;

  // 这里主要就是找到那个偏移大于现在的点
  while (
    index < itemCount &&
    getItemMetadata(props, index, instanceProps).offset < offset
  ) {
    index += interval;
    interval *= 2;
  }
  // 找到那个点后就可以使用二分查找了
  return findNearestItemBinarySearch(
    props,
    instanceProps,
    Math.min(index, itemCount - 1),
    Math.floor(index / 2),
    offset
  );
};

接下来再看看getStopIndexForStartIndex

getStopIndexForStartIndex: (
  props: Props<any>,
  startIndex: number,
  scrollOffset: number,
  instanceProps: InstanceProps
): number => {
  const { direction, height, itemCount, layout, width } = props;

  const isHorizontal = direction === 'horizontal' || layout === 'horizontal';
  // 可见区域的滑动方向的长度
  const size = (((isHorizontal ? width : height): any): number);
  const itemMetadata = getItemMetadata(props, startIndex, instanceProps);
  // 距离第一个的最大距离
  const maxOffset = scrollOffset + size;

  // 可见区域里第一个的偏移
  let offset = itemMetadata.offset + itemMetadata.size;
  let stopIndex = startIndex;

  while (stopIndex < itemCount - 1 && offset < maxOffset) {
    stopIndex++;
    offset += getItemMetadata(props, stopIndex, instanceProps).size;
  }

  return stopIndex;
},
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant