About vue’s scrollBehavior (scrolling behavior)

We will encounter a problem in actual development:
we scroll down on a long list page, and then click on a certain data in the list to enter the details page to view. At this point we decided to go back to the list and continue looking at the list.
In many cases, because the components of the list page have been destroyed, when we return to the list page, the page will be on the top and we have to pull down to view the list again. This results in a lot of unnecessary operations and does not meet the user's expectations.

The user hopes to return after viewing the play details page. The position returned to the list page is the position just browsed.

What is a good solution to this situation?

Here are 3 solutions:

1. Use <keep-alive> cache, that is, do not destroy the list page

APP.js

<template>
  <div id="app">
    <!-- <router-view/> -->
    <keep-alive>
        <router-view v-if="$route.meta.keepAlive"></router-view>
    </keep-alive>
    <router-view v-if="!$route.meta.keepAlive" />
  </div>
</template>

router.js in

 routes: [
    {
      path: '/',
      name: 'List',
      //component: List
      component: () => import('./views/index/list.vue'),
      meta: {
        keepAlive: true // 需要缓存
      }
    },
    {
      path: '/content/:contentId',
      name: 'content',
      component: () => import('./views/index/content.vue'),
      meta: {
        keepAlive: false // 不需要缓存
      }
    },
]

The details page does not need to be cached, but the list page does.

2. Use route guards

The principle is to record the current page scroll position in the routing hook of beforeRouterLeave

//在页面离开时记录滚动位置,这里的this.scrollTop可以保存在vuex的state或者浏览器本地
beforeRouteLeave (to, from, next) {
    this.scrollTop = document.documentElement.scrollTop || document.body.scrollTop
    next()
  },

//进入该页面时,用之前保存的滚动位置赋值
beforeRouteEnter (to, from, next) {
    next(vm => {
      document.body.scrollTop = vm.scrollTop
    })
  },

This.scrollTop here can be saved in the state of vuex or locally in the browser

3. Use vue-router method scrollBehavior (recommended)

router.js in

const scrollBehavior = function scrollBehavior (to, from, savedPosition) {
  if (savedPosition) {
    // savedPosition 会在你使用浏览器前进或后退按钮时候生效
    // savedPosition: 会记录滚动条的坐标,点击"后退/前进" 时的记录值(x:?,y:?)
    return savedPosition;
  }else {
      return { x: 0, y: 0 }; // 期望滚动的位置
   }
};
const router = new Router({
  routes,
  scrollBehavior,
});

 This solution is processed directly in the routing, is compatible with every page, and does not generate a scroll position of 1px after the page is loaded.

scrollBehavior (to, from, savedPosition)Methods to receive  to and  from route objects. The third parameter  is available savedPositionif and only when  popstate navigating (triggered via the browser's forward/back buttons) .

parameter:

        to: The target routing object to enter, where to go

        from: Where does the leaving routing object come from?

        savedPosition: will record the coordinates of the scroll bar and the recorded value when "Back/Forward" is clicked (x:?,y:?)

scrolling behavior

We can  vue-router customize how the page scrolls when switching routes. For example, when jumping to a new route, the page scrolls to a certain position; when switching routes, the page returns to the previous scroll position.
When creating a route instance, we only need to provide a  scrollBehavior method:

const router = createRouter({
  history: createWebHashHistory(),
  routes: [...],
  scrollBehavior (to, from, savedPosition) {
    // return 期望滚动到哪个的位置
  }
})

scrollBehavior Functions receive  to and  from route objects. Third parameter  , only  available  savedPositionif this is a  navigation (clicking the browser's back/forward buttons, or calling  a method)popstaterouter.go()

Scroll to a fixed distance

This function can return a  ScrollToOptions location object:

const router = createRouter({
  scrollBehavior(to, from, savedPosition) {
    // 始终滚动到顶部
    return { top: 0 }
  },
})

Scroll to element position

This can be done by  el passing a  CSS selector or an  DOM element . In this case, top and  left will be treated as the relative offset of that element.

const router = createRouter({
  scrollBehavior(to, from, savedPosition) {
    // 始终在元素 #main 上方滚动 10px
    return {
      // el: document.getElementById('main'),
      el: '#main',
      top: -10,
    }
  },
})

Scroll to anchor position

const router = createRouter({
  scrollBehavior(to, from, savedPosition) {
    if (to.hash) {
      return {
        el: to.hash,
      }
    }
  },
})

Scroll to previous position

When the browser  后退/前进 button is pressed, or  router.go() a method is called, the page will return to the previous scroll position:

const router = createRouter({
  scrollBehavior(to, from, savedPosition) {
    if (savedPosition) {
      return savedPosition
    } else {
      return { top: 0 }
    }
  },
})

Note: If  false a value of one is returned, or is one 空对象, no scrolling will occur . We can also add it to the returned object  behavior: 'smooth' to make the scrolling smoother .

delayed scrolling

Sometimes we don't want the scrolling behavior to be performed immediately. For example, when the page has a transition effect, we hope that the scrolling will be performed after the transition is completed. To do this we can return a  Promise:

const router = createRouter({
  scrollBehavior(to, from, savedPosition) {
    return new Promise((resolve, reject) => {
      setTimeout(() => {
        resolve({ left: 0, top: 0 })
      }, 500)
    })
  }
})

 

Guess you like

Origin blog.csdn.net/muzidigbig/article/details/131709194