首页 > 解决方案 > 使用行为平滑的 window.scrollTo 时避免处理 IntersectionObserver

问题描述

我正在使用 nuxt 创建登录页面,我使用哈希来指示页面上的每条路线,为此我使用scrollBehavior来处理路线上的哈希并平滑滚动到部分:

  router: {
    scrollBehavior: async (to, from, savedPosition) => {
      console.log(to, from, savedPosition);
      if (savedPosition) {
        return savedPosition;
      }

      const findEl = async (hash, x) => {
        return (
          document.querySelector(hash) ||
          new Promise((resolve, reject) => {
            if (x > 50) {
              return resolve();
            }
            setTimeout(() => {
              resolve(findEl(hash, ++x || 1));
            }, 100);
          })
        );
      };

      console.log("to.hash", to.hash);
      if (to.hash) {
        let el = await findEl(to.hash);
        console.log("el", el);
        if ("scrollBehavior" in document.documentElement.style) {
          return window.scrollTo({ top: el.offsetTop, behavior: "smooth" });
          // removing behavior not cause conflicts
          //return window.scrollTo(0, el.offsetTop);
        } else {
          return window.scrollTo(0, el.offsetTop);
        }
      }

      return { x: 0, y: 0 };
    }
  },

而且我也在使用IntersectionObserver,所以当用户滚动时,如果部分在屏幕视图中出现至少 60%,我会替换 nuxt 上的路线。

问题是当用户在第 1 部分并且他们想去第 3 部分时,作为第 2 部分出现在屏幕上的观察者句柄处理这条路线并避免将用户发送到第 3 部分。

当我使用滚动平滑行为更新 nuxt 上的路线时,我不确定如何避免 hanlde IntersectionObserver 事件。

    observeSections() {
      console.log("this.sectionObserver", this.sectionObserver);
      try {
        this.sectionObserver.disconnect();
      } catch (error) {}

      const options = {
        rootMargin: "0px",
        threshold: 0.6,
      };
      this.sectionObserver = new IntersectionObserver(
        this.sectionObserverHandler,
        options
      );

      // Observe each section
      const sections = document.querySelectorAll(".section");
      sections.forEach((section) => {
        this.sectionObserver.observe(section);
      });
    },
    sectionObserverHandler(entries) {
      for (const entry of entries) {
        if (entry.isIntersecting) {
          const sectionId = entry.target.id;
          console.log("intersection in", sectionId);
          // Push sectionId to router here
          this.$router.replace({
            name: this.$route.name,
            hash: `#${sectionId}`,
          });
        }
      }
    },

如果你想重现我的项目,我会用我的工作创建一个简单的 nuxt 应用程序。尝试从第 1 部分转到第 3 或 4 部分,您会看到它在第 2 部分停止。 CodeSandBox:https ://codesandbox.io/s/optimistic-bash-y8ccz

标签: javascriptvue.jsnuxt.jsvue-routerintersection-observer

解决方案


推荐阅读