Skip to content
字数
239 字
阅读时间
2 分钟

DOM 结构

jsx
<div ref={root} role="feed" class={bem()} aria-busy={loading.value}>
  {props.direction === "down" ? Content : Placeholder}
  {renderLoading()}
  {renderFinishedText()}
  {renderErrorText()}
  {props.direction === "up" ? Content : Placeholder}
</div>

核心处理逻辑

ts
// 监听事件
useEventListener("scroll", check, {
  target: scrollParent,
  passive: true,
});
ts
const check = () => {
  nextTick(() => {
    if (
      loading.value ||
      props.finished ||
      props.disabled ||
      props.error ||
      // skip check when inside an inactive tab
      tabStatus?.value === false
    ) {
      return;
    }

    const { direction } = props;
    const offset = +props.offset;
    const scrollParentRect = useRect(scroller);

    if (!scrollParentRect.height || isHidden(root)) {
      return;
    }

    let isReachEdge = false;
    const placeholderRect = useRect(placeholder);

    if (direction === "up") {
      // 监听计算是否到达边缘
      isReachEdge = scrollParentRect.top - placeholderRect.top <= offset;
    } else {
      isReachEdge = placeholderRect.bottom - scrollParentRect.bottom <= offset;
    }

    if (isReachEdge) {
      loading.value = true;
      emit("update:loading", true);
      emit("load");
    }
  });
};

细节处理

当窗口激活时,触发 check 函数

ts
if (tabStatus) {
  watch(tabStatus, (tabActive) => {
    if (tabActive) {
      check();
    }
  });
}

组件内部 loading 状态的改变在 onUpdated 之后

ts
// bad
watchEffect(() => {
  loading.value = props.loading!;
});
// good —— 确保 dom 已经更新,而后续的状态更新并不会影响 DOM 变化
onUpdated(() => {
  loading.value = props.loading!;
});

贡献者

chenjie

文件历史