Practice scenario requirements

  • In a product list, it is common to scroll to a certain point, click to view product information, and then go back to the original scrolling position
  • All pages are in router-view, and keep-alive is temporarily used to cache all pages, so the data need to be updated when the lists of products of different categories and the detailed pages of different products are entered

First note:

  • This practice test environment is webKit kernel browser on PC, not mobile phone
  • Using $router.back(-1) has the same effect as the browser back button
  • Keep-alive must be used to cache the routing page to remember the last location, otherwise a browser retreat or $route. back retreat will reload the data and change the height of the original content
  • The Activated event can be used only after keep-alive is used

Record the height position of the last list scroll, restored when backward

The idea is simple: set a variable in the routing meta information: scrollToTop, which indicates whether the flag should go back to the top of our product page
productListIs to restore the last scroll height, not back to the top, so set to false


When leaving the route, check whether this variable is false or not, and record the scrolling height in vuEX (so this variable has two functions, you can maintain two).


Then, when entering the routing page, if the scrollToTop of this route is false, the height of the last record is read from vuEX and restored


First of all, note that vUE is a single page application. When switching routes, the scrolling height does not change, because switching routes only switches the content of the page and the scrolling height


It’s a “BUG” when you scroll 100 pixels on a routing page and then switch to a new routing page (changing the content of the page), as long as the new routing page also scrolls 100 pixels and the scrolling height stays the same when you go back.


So in this code we default to scrollToTop being true and set the scroll height to 0


Configuration in my route:

routes: [{
            path: '/',
            name: 'home',
            component: Home,
            meta: { title: "Phoenix Tour" ,scrollToTop:true}
        },
        {
            path: '/product',
            name: 'product',
            component: () => import('./views/Product.vue'),
            meta: { title: "Travel" ,scrollToTop:true}
        },
        {
            path: '/productList/:id',
            name: 'productList',
            component: () => import('./views/productList.vue'),
            meta: { title: "A list" ,scrollToTop:false}
        },
        {
            path: '/productShow/:id',
            name: 'productShow',
            component: () => import('./views/productShow.vue'),
            meta: { title: "Tourism Product Display" ,scrollToTop:true}}]Copy the code

Next, in store.js, maintain a variable for the record

import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

export default new Vuex.Store({
  state: {
    scrollTop :0
  },
  mutations: {
      recordScrollTop(state,n){
          state.scrollTop = n
      }
  },
  actions: {

  }
})Copy the code

In the related routing event in main.js

router.beforeEach(function(to,from,next){document.title = to.meta. Title // To leave the page if you set it not to roll back to the top, then remember to scroll up to the height in vuex so that you can restore the height next timeif(from.meta.scrollToTop==false) {
        store.commit('recordScrollTop'Next, document. DocumentElement. ScrollTop)} ()}) router. AfterEach ((to and from) = > {/ / if the page after entering to scroll to the top, Set scrollTop = 0 // otherwise read from vuex the height remembered last time you left the page and restore itif(to.meta.scrollToTop==true) {setTimeout(()=>{
            document.documentElement.scrollTop = 0
        },10)
    }else{
        setTimeout(()=>{
            document.documentElement.scrollTop = store.state.scrollTop
        },50)

    }
});Copy the code

/* * Set scrollTop to router. AfterEach; /* * Set scrollTop to router. AfterEach is a DOM update that is triggered only after the afterEach call is madesetIn Timeout, otherwise I try something wrong.. * /Copy the code

After using keep-alive to cache the page, update the data when the parameters are different

When entering the product list page of different categories, or the product page of different ids, because of the cache of the last result, of course, we need to deal with the update


With keep-alive, the route page can use the activated event, because with keep-alive other normal life cycles are executed only once, whereas the activated event is activated every time the display page is displayed (similar to onShow for applets) and must be updated using this event


Maintain an ID in the data page. The value of activated is 0 by default. Invoke the activated event every time you log in to the page


If not, update the relevant data according to this ID, and update the ID in the data to the new ID, and don’t forget to empty the product data of the last classification


Of course, you should initially read data once, such as in Created, whereas Activated does not activate the first time the page is created, and only activates the second time it is cached (I think so).

The code:

activated(){// Since this page is cached, each activation of the page must determine whether to reset the relevant parameters and reload the dataif(this.id ! == this.$route.params.id){this.id = this.$routeThis.curpage = 1 this.product = [] this.product ()'/api/productList.php',this.id,this.curpage).then((res)=>{
                this.ptotal = res.total
                res.products.forEach((item)=>{
                    this.product.push (item)
                })
                this.loading = false}}})Copy the code

If updated or corrected then added.