【问题标题】:How to change the hash in the URL dynamically when i scroll over components in vue.js?当我滚动 vue.js 中的组件时,如何动态更改 URL 中的哈希?
【发布时间】:2021-09-21 11:51:16
【问题描述】:

我有一个包含多个组件的单页 vue.js 应用程序,现在我想在滚动浏览组件时动态更改 url 中的哈希值。例如,如果您尝试在 vue.js 文档中滚动:

从这里滚动时,您会发现 url 发生变化:

https://v3.vuejs.org/guide/introduction.html#what-is-vue-js

到这里:

https://v3.vuejs.org/guide/introduction.html#getting-started

等等。

我尝试在组件的第一个标签上设置@scroll="changeRoute",这会触发一个函数:

<script>
import { useRouter } from "vue-router";
export default {
  setup() {
    const router = useRouter();
    const changeRoute = () => {
      router.push({
        name: "Home",
        hash: "#landing-section",
      });
      console.log("route changes");
    };
    return {
      changeRoute,
    };
  },
};
</script>

但这不起作用,甚至没有执行的功能?

【问题讨论】:

  • 很有可能,您的组件没有触发滚动事件。您应该将滚动事件附加到可滚动的父级(可能是 html/body 元素)。此外,您可能需要考虑使用 IntersectionObserver,并检查当前哪个组件与视口相交:然后将散列更新为与该组件关联的标识符。
  • 我去搜一下
  • “我该怎么做?”我在评论中所说的。

标签: vue.js vue-router


【解决方案1】:

为了帮助您入门,并且因为您提供了 vue 文档作为示例,您可以在他们的页面上查看它是如何工作的。

他们使用了一个名为 VuePress 的包,它有一个 setActiveHash 函数。

看起来他们debounce滚动事件,然后使用querySelectorAll获取他们想要更改哈希的所有元素,然后查找这些元素是否处于活动状态,然后用活动元素替换当前哈希哈希。

/* global AHL_SIDEBAR_LINK_SELECTOR, AHL_HEADER_ANCHOR_SELECTOR */

import debounce from 'lodash.debounce'

export default {
  mounted () {
    window.addEventListener('scroll', this.onScroll)
  },

  methods: {
    onScroll: debounce(function () {
      this.setActiveHash()
    }, 300),

    setActiveHash () {
      const sidebarLinks = [].slice.call(document.querySelectorAll(AHL_SIDEBAR_LINK_SELECTOR))
      const anchors = [].slice.call(document.querySelectorAll(AHL_HEADER_ANCHOR_SELECTOR))
        .filter(anchor => sidebarLinks.some(sidebarLink => sidebarLink.hash === anchor.hash))

      const scrollTop = Math.max(
        window.pageYOffset,
        document.documentElement.scrollTop,
        document.body.scrollTop
      )

      const scrollHeight = Math.max(
        document.documentElement.scrollHeight,
        document.body.scrollHeight
      )

      const bottomY = window.innerHeight + scrollTop

      for (let i = 0; i < anchors.length; i++) {
        const anchor = anchors[i]
        const nextAnchor = anchors[i + 1]

        const isActive = i === 0 && scrollTop === 0
          || (scrollTop >= anchor.parentElement.offsetTop + 10
            && (!nextAnchor || scrollTop < nextAnchor.parentElement.offsetTop - 10))

        const routeHash = decodeURIComponent(this.$route.hash)
        if (isActive && routeHash !== decodeURIComponent(anchor.hash)) {
          const activeAnchor = anchor
          // check if anchor is at the bottom of the page to keep $route.hash consistent
          if (bottomY === scrollHeight) {
            for (let j = i + 1; j < anchors.length; j++) {
              if (routeHash === decodeURIComponent(anchors[j].hash)) {
                return
              }
            }
          }
          this.$vuepress.$set('disableScrollBehavior', true)
          this.$router.replace(decodeURIComponent(activeAnchor.hash), () => {
            // execute after scrollBehavior handler.
            this.$nextTick(() => {
              this.$vuepress.$set('disableScrollBehavior', false)
            })
          })
          return
        }
      }
    }
  },

  beforeDestroy () {
    window.removeEventListener('scroll', this.onScroll)
  }
}

【讨论】:

    猜你喜欢
    • 2015-05-01
    • 2021-10-14
    • 2013-03-31
    • 2014-12-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多