Как обрабатывать якоря (закладки) с маршрутизатором Vue?

Я ищу умный способ обработки якорей на странице с маршрутизатором Vue. Рассмотрим следующее:

<router-link to="#app">Apply Now</router-link>
<!-- some HTML markup in between... -->
<div id="app">...</div>

поведение "прокрутка к якорю"описано в документации работает нормально, за исключением:

  • когда вы нажимаете на якорь, он приводит вас к div id="app". Теперь прокрутите от div назад к якорю и попробуйте нажать его снова - на этот раз вы будете не спрыгнуть на div. На самом деле, якорь сохранить класс router-link-active и URL-адрес по-прежнему будет содержать хэш -/#app;
  • С шагами выше, если вы обновите страницу (URL-адрес все равно будет содержать хэш) и нажмите на якорь, ничего не произойдет.

это очень неудачно с точки зрения UX, потому что потенциальный клиент должен вручную прокрутить весь путь вниз снова, чтобы добраться до раздела Приложения.

мне было интересно, охватывает ли маршрутизатор Vue эту ситуацию. Для ссылка, вот мой маршрутизатор:

export default new VueRouter({
    routes,
    mode: 'history',
    scrollBehavior(to, from, savedPosition) {
        if (to.hash) {
            return { selector: to.hash }
        } else if (savedPosition) {
            return savedPosition;
        } else {
            return { x: 0, y: 0 }
        }
    }
})

3 ответов


Я не нашел ничего в ресурсах, чтобы решить вашу проблему, но вы могли бы utitlize $route.hash в своем mounted крюк компонента, который держит ваш <router-view></router-view> для решения проблемы обновления.

<script>
export default {
  name: 'app',
  mounted: function()
  {
    // From testing, without a brief timeout, it won't work.
    setTimeout(() => this.scrollFix(this.$route.hash), 1),
  },
  methods: {
    scrollFix: function(hashbang)
    {
      location.href = hashbang;
    }
  }
}
</script>

затем, чтобы решить проблему вторых кликов, вы можете использовать native модификатор и привязка к вашему <router-link></router-link>. Это довольно ручной процесс, но он будет работать.

<router-link to="#scroll" @click.native="scrollFix('#scroll')">Scroll</router-link>

также может быть что-то, что вы можете сделать с маршрутизатором afterEach метод, но не понял что еще.


возможное решение, которое более resusable IMO:

this.$router.push({ name: 'home' }, undefined, () => { location.href = this.$route.hash })

поскольку 3-й аргумент является функцией abort (), он может иметь нежелательные побочные эффекты..

если вы хотите использовать его глобально, добавьте функцию к маршрутизатору:

pushWithAnchor: function (routeName, toHash) {
    const fromHash = Router.history.current.hash
    fromHash !== toHash || !fromHash
    ? Router.push({ name: routeName, hash: toHash })
    : Router.push({ name: routeName, hash: fromHash }, undefined, () => { window.location.href = toHash })
  }

и используйте его в компонентах с:

this.$router.options.pushWithAnchor('home', '#fee-calculator-section')

в шаблоне вы можете сделать что-то вроде:

<a @click="this.$router.options.pushWithAnchor('home', '#fee-calculator-section')"></a>

к сожалению вы не можете использовать свиток смещение хотя


я использовал такое решение:

<router-link to="/about" @click.native="scrollFix('#team')" >The team</router-link>

и так:

methods: {
    scrollFix: function(hash) {
      setTimeout(() => $('html, body').animate({
      scrollTop: $(hash).offset().top
      }, 1000), 1)
    }
  }