Vue.js - это простой в использовании фреймворк для веб-приложений, который мы можем использовать для разработки интерактивных интерфейсных приложений.

Vue Router - это URL-маршрутизатор, который сопоставляет URL-адреса с компонентами.

В этой статье мы рассмотрим, как изменить поведение прокрутки маршрутов Vue Router.

Изменение поведения прокрутки

Иногда нам может потребоваться прокрутка вверх при переходе к новому маршруту или сохранение положения прокрутки объектов истории, как при перезагрузке реальной страницы.

Vue Router позволяет нам настраивать поведение прокрутки так, как нам нравится, когда маршрут загружается.

Это работает, только если браузер поддерживает history.pushState.

Мы можем настроить поведение прокрутки, предоставив функцию scrollBehavior.

Он имеет объекты маршрута to и from в качестве первых двух параметров. Третий аргумент - savePosition, доступен только в том случае, если это popstate навигация, запускаемая кнопками браузера "Назад" или "Вперед".

Функция может возвращать объект позиции прокрутки в виде:

{ x: number, y: number }

or:

{ selector: string, offset? : { x: number, y: number }}

offset поддерживается начиная с Vue Router 2.6.0

Например, мы можем добавить scrollBehavior к нашим маршрутам следующим образом:

src/index.js:

const Foo = {
  template: `
    <div>
      <div v-for='n in 100'>{{n}} foo</div>
    </div>
  `
};
const Bar = {
  template: `
  <div>
    <div v-for='n in 100'>{{n}} bar</div>
  </div>
  `
};
const routes = [
  {
    path: "/foo",
    component: Foo
  },
  {
    path: "/bar",
    component: Bar
  }
];
const router = new VueRouter({
  routes,
  scrollBehavior(to, from, savedPosition) {
    return { x: 0, y: 0 };
  }
});
new Vue({
  el: "#app",
  router
});

index.html :

<!DOCTYPE html>
<html>
  <head>
    <title>App</title>
    <meta charset="UTF-8" />
    <script src="https://unpkg.com/vue/dist/vue.js"></script>
    <script src="https://unpkg.com/vue-router/dist/vue-router.js"></script>
  </head>
  <body>
    <div id="app">
      <router-view></router-view>
      <router-link to="foo">Foo</router-link>
      <router-link to="bar">Bar</router-link>
    </div>
    <script src="src/index.js"></script>
  </body>
</html>

В приведенном выше коде мы имеем:

scrollBehavior(to, from, savedPosition) {
  return { x: 0, y: 0 };
}

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

Если мы вернем что-то ложное или пустой объект, прокрутки не произойдет.

Если мы изменим scrollBehavior на:

scrollBehavior(to, from, savedPosition) {
  if (savedPosition) {
    return savedPosition;
  } else {
    return { x: 0, y: 0 };
  }
}

Затем мы сохраняем позицию прокрутки страницы при перемещении вперед и назад с помощью кнопок вперед и назад.

Мы можем создать поведение прокрутки до привязки, установив идентификатор для наших элементов, а затем изменив scrollBehavior следующим образом:

src/index.js :

const Foo = {
  template: `
    <div>
      <div v-for='n in 100' :id='n'>{{n}} foo</div>
    </div>
  `
};
const routes = [
  {
    path: "/foo",
    component: Foo
  }
];
const router = new VueRouter({
  routes,
  scrollBehavior(to, from, savedPosition) {
    if (to.hash) {
      return {
        selector: to.hash
      };
    }
  }
});
new Vue({
  el: "#app",
  router
});

index.html :

<!DOCTYPE html>
<html>
  <head>
    <title>App</title>
    <meta charset="UTF-8" />
    <script src="https://unpkg.com/vue/dist/vue.js"></script>
    <script src="https://unpkg.com/vue-router/dist/vue-router.js"></script>
  </head>
  <body>
    <div id="app">
      <router-view></router-view>
    </div>
    <script src="src/index.js"></script>
  </body>
</html>

Затем, когда мы переходим к /#/foo#100, мы прокручиваем вниз, затем, когда мы переходим к /#/foo#20, мы видим 20 foo в верхней части экрана.

Асинхронная прокрутка

Мы также можем выполнять асинхронную прокрутку с scrollBehavior, начиная с Vue Router 2.8.0, возвращая обещание, которое разрешается к тем же объектам, что и синхронная прокрутка.

Например, мы можем изменить приведенный выше пример на:

src/index.js :

const Foo = {
  template: `
    <div>
      <div v-for='n in 100' :id='n'>{{n}} foo</div>
    </div>
  `
};
const routes = [
  {
    path: "/foo",
    component: Foo
  }
];
const router = new VueRouter({
  routes,
  scrollBehavior(to, from, savedPosition) {
    if (to.hash) {
      return new Promise((resolve, reject) => {
        setTimeout(() => {
          resolve({
            selector: to.hash
          });
        }, 1000);
      });
    }
  }
});
new Vue({
  el: "#app",
  router
});

Затем, когда мы переходим к /#/foo#100 в нашем браузере, через секунду мы прокручиваем страницу вниз.

Заключение

Поведение прокрутки во время навигации по маршруту можно изменить, добавив функцию scrollBehavior к нашему объекту router. Он принимает параметры to и from, которые являются объектами маршрута, и третий параметр savedPosition с сохраненной позицией прокрутки пройденного маршрута.

Поведение прокрутки может быть синхронным или асинхронным, начиная с Vue Router 2.8.0.

Мы можем перейти к элементу с помощью селектора CSS или позиции.