Vue项目中scrollTo在加载好后回到原来的地方?

新手上路,请多包涵

我想要在页面加载好后通过scrollTo进行滚动,虽然在加载时它到了正确的地方,但是在加载完成时又会回到之前的地方,我是在mounted调用这个函数的:

to: function() {
  window.scrollTo(0, $("#to").offset().top);
}
阅读 1.2k
avatarAI BotBETA

在Vue项目中,如果你遇到在mounted钩子中使用scrollTo方法后页面又跳回到原来位置的问题,这通常是因为页面上的某些元素(如图片、异步数据等)在mounted钩子执行时尚未完全加载完成,导致页面高度在scrollTo执行后发生了变化。

为了解决这个问题,你可以考虑以下几种方法:

1. 使用nextTick

Vue的nextTick方法可以在DOM更新完成后立即执行你的回调函数。这可以确保在调用scrollTo之前,所有依赖的数据和DOM都已经更新完毕。

export default {
  mounted() {
    this.$nextTick(() => {
      this.to();
    });
  },
  methods: {
    to() {
      window.scrollTo(0, $("#to").offset().top);
    }
  }
}

2. 监听图片加载

如果你的页面中有大量图片,并且这些图片的大小对页面滚动位置有影响,你可以监听图片的加载状态,在所有图片加载完成后执行滚动。

export default {
  data() {
    return {
      imagesLoaded: 0,
      totalImages: 0
    };
  },
  mounted() {
    this.totalImages = document.querySelectorAll('img').length;
    document.querySelectorAll('img').forEach(img => {
      img.onload = () => {
        this.imagesLoaded++;
        if (this.imagesLoaded === this.totalImages) {
          this.to();
        }
      };
    });
  },
  methods: {
    to() {
      window.scrollTo(0, $("#to").offset().top);
    }
  }
}

3. 使用Vue Router的导航守卫

如果你的页面跳转是通过Vue Router实现的,并且你希望在路由跳转完成后滚动到特定位置,你可以使用Vue Router的导航守卫。

router.beforeEach((to, from, next) => {
  // 可以在这里设置滚动位置,但通常不推荐,因为可能不是所有路由跳转都需要滚动
  next();
});

// 或者在组件内使用
export default {
  watch: {
    '$route'(to, from) {
      this.$nextTick(() => {
        this.to();
      });
    }
  },
  methods: {
    to() {
      window.scrollTo(0, $("#to").offset().top);
    }
  }
}

4. 延迟执行

如果上述方法都不适用,你可以简单地使用setTimeout来延迟scrollTo的执行,但这通常不是最佳实践,因为它依赖于不确定的时间间隔。

mounted() {
  setTimeout(() => {
    this.to();
  }, 500); // 延迟500毫秒执行
},
methods: {
  to() {
    window.scrollTo(0, $("#to").offset().top);
  }
}

在实际应用中,推荐使用nextTick方法,因为它既简单又可靠,能够确保DOM更新完成后再执行滚动操作。

1 个回答

可以试试在路由上做处理

1. 基础用法:滚动到页面顶部

每次导航时,页面都滚动到顶部:

const router = new VueRouter({
  routes: [
    // 你的路由配置
  ],
  scrollBehavior() {
    return { x: 0, y: 0 };
  }
});

2. 恢复滚动位置

如果存在保存的滚动位置(如浏览器的前进/后退),则滚动到该位置:

const router = new VueRouter({
  routes: [
    // 你的路由配置
  ],
  scrollBehavior(to, from, savedPosition) {
    if (savedPosition) {
      return savedPosition;
    } else {
      return { x: 0, y: 0 };
    }
  }
});

3. 滚动到特定元素

如果 URL 中包含 hash(例如 #section1),滚动到对应的元素:

const router = new VueRouter({
  routes: [
    // 你的路由配置
  ],
  scrollBehavior(to, from, savedPosition) {
    if (savedPosition) {
      return savedPosition;
    } else if (to.hash) {
      return {
        selector: to.hash
      };
    } else {
      return { x: 0, y: 0 };
    }
  }
});

4. 按条件滚动

你可以根据目标路由或其他条件自定义滚动行为,例如某些特定页面滚动到特定位置:

const router = new VueRouter({
  routes: [
    // 你的路由配置
  ],
  scrollBehavior(to, from, savedPosition) {
    if (savedPosition) {
      return savedPosition;
    } else if (to.path === '/specific-page') {
      return { x: 0, y: 500 }; // 特定页面滚动到特定位置
    } else if (to.hash) {
      return {
        selector: to.hash
      };
    } else {
      return { x: 0, y: 0 };
    }
  }
});

5. 延迟滚动(等待页面内容加载)

有时你可能希望在页面内容加载完成后再滚动,可以使用 setTimeout 来延迟滚动:

const router = new VueRouter({
  routes: [
    // 你的路由配置
  ],
  scrollBehavior(to, from, savedPosition) {
    return new Promise((resolve) => {
      setTimeout(() => {
        if (savedPosition) {
          resolve(savedPosition);
        } else {
          resolve({ x: 0, y: 0 });
        }
      }, 500); // 延迟500ms
    });
  }
});

6. 动画滚动

如果你想让页面滚动有平滑的动画效果,可以使用 window.scrollTo 的配置项 behavior

const router = new VueRouter({
  routes: [
    // 你的路由配置
  ],
  scrollBehavior(to, from, savedPosition) {
    if (savedPosition) {
      return { ...savedPosition, behavior: 'smooth' };
    } else {
      return { x: 0, y: 0, behavior: 'smooth' };
    }
  }
});
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题
宣传栏