Волшебное использование scrollBehavior в vue-router

внешний интерфейс Vue.js vue-router

1. keep-alive

  • вопрос:После использования тега keep-alive расположение страницы кеша, возвращаемой на некоторые устройства Android, является неточным.

  • решение:

<div id="app">
    <keep-alive>
      <router-view v-if="$route.meta.keepAlive"></router-view>
    </keep-alive>
    <router-view v-if="!$route.meta.keepAlive"></router-view>
</div>
const router = new Router({
  scrollBehavior(to, from, savedPosition) {
    if (savedPosition && to.meta.keepAlive) {
      return savedPosition;
    }
    return { x: 0, y:0 };
  },
});

2. Проблема с пустым экраном при возврате страницы

  • вопрос
【前提】:iOS设备
【步骤】: 页面A是个列表很长-->滑到页脚的时候点击跳转之后到页面B--->再返回A页面
         --->屏幕会出现空白遮罩层--->手指轻触屏幕滑动--->遮罩层消失

问题图片

Решение первое

Эта операция выполняется после операции обратного вызова после успешного запроса интерфейса, например

// fetchCourseList是一个封装好的Promise请求
fetchCourseList().then(({ data: courses }) => {
  this.courses = courses;
}).then(() => {
    setTimeout(() => {
        window.scrollTo(0, 1);
        window.scrollTo(0, 0);
    });
});

Недостатки этой схемы: Каждая страница должна выполнять такую ​​обработку, что не рекомендуется.

Решение второе (рекомендуется)

Использование асинхронных операций прокрутки в scrollBehavior

const router = new Router({
  scrollBehavior(to, from, savedPosition) {
    // keep-alive 返回缓存页面后记录浏览位置
    if (savedPosition && to.meta.keepAlive) {
      return savedPosition;
    }
    // 异步滚动操作
    return new Promise((resolve) => {
      setTimeout(() => {
        resolve({ x: 0, y: 1 });
      }, 0);
    });
  },
});

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

Почему нельзя вернуться напрямую и нужно использовать асинхронную операцию прокрутки? Ниже приведены некоторые личные мнения, и я приглашаю всех обсудить и исправить.

  1. Прежде всего, нам нужно понять, какой жизненный цикл компонента функция Scrollbehavior начинает выполнять. Здесь я предупреждаю каждого жизненного цикла компонента и функции Scrollbehavior, и результатом расследования: функция Scrollbehavior выполняется до того, как загружена непрерывная упадинат после установки жизненного цикла компонента.

  2. В функции scrollBehavior верните { x:0, y:100} напрямую, и страница входа по-прежнему будет вверху. Почему не прокручивается до 100px? Угадайте: данные, возвращаемые асинхронным запросом в смонтированном состоянии, назначаются переменной a в данных.Переменная a вызывает сбой прокрутки, потому что двусторонняя привязка vue обновляет слой представления?

  3. Чтобы проверить вышеприведенные догадки, установите данные статической страницы, которые были жестко запрограммированы на html. В функции scrollBehavior верните { x:0, y: 100} напрямую, и результат: при входе на страницу она будет прокручиваться до 100 пикселей. Доказательство: это как-то связано с операцией после возврата асинхронного запроса.

  4. Затем поймите, что vue смонтировал и сделал перед периодами обновления. смонтированный период: data данные висели на странице. BeforeUpdate и период обновления: когда vue обнаруживает, что данные в данных изменились, он инициирует повторную визуализацию соответствующего компонента.

  5. Согласно шагу 4. Асинхронный запрос, инициированный в течение смонтированного периода, не будет мешать последующей работе основного потока, поэтому функция scrollBehavior продолжит выполнение, если не сработает событие обратного вызова запроса (операция присваивания переменной a в данные не выполняются). Если вы сразу вернете { x:0, y:100} в это время. Это эквивалентно прокрутке перед выполнением события обратного вызова асинхронного запроса. После прокрутки начинает выполняться событие обратного вызова асинхронного запроса, и присваивается переменная a в данных, что приводит к повторному рендерингу компонента и возврату наверх. Весь процесс прокрутки прокручивается для исходной страницы данных данных, поэтому слой маски все равно будет отображаться.

  6. Подводя итог вышесказанному: вы должны использовать асинхронную прокрутку, использовать setTimeout, чтобы выйти из основного потока и поместить событие обратного вызова в очередь. Поскольку moused выполняется раньше, чем функция scrollBehavior, событие обратного вызова асинхронного запроса входит в очередь первым, а затем событие обратного вызова setTimeout. По принципу «первым пришел – первым вышел». Сначала выполняется событие обратного вызова асинхронного запроса для присвоения переменной a в данных. На данный момент это эквивалентно статической странице, а затем мне просто нужно выполнить return { x: 0, y: 100 }. Это вызвало эффект прокрутки страницы до 100 пикселей. Но поскольку данные данных изменились, страница повторно отображается вверху. В настоящее время весь эффект касания и прокрутки был выполнен тайно, и слой маски больше не будет отображаться.