The introduction

In order to pursue the meticulous experience similar to native mode, front-end WebApp applications are always constantly approaching the native experience. For example, as for the function to be mentioned in this paper, native is a multi-page application, so a new page can be opened with a new WebView. In fact, backward is to close the current WebView, and the previous webview will be displayed naturally. However, in single-page WebApp applications, all contents are actually displayed in one page, and there is no multi-page situation. At this time, front-end development is needed to find ways to achieve the corresponding experience effect.

First of all, by forward refresh and backward refresh, I mean whether the component is re-rendered, such as listing A, where clicking on each item goes to Detail B, and then backing from B to Listing A does not re-render or re-send ajax requests. Below, we said in vue single page application, to achieve forward refresh backward not refresh some implementation scheme, other schemes we can supplement together.

Keep – the alive

Keep-alive is a vue method for caching component instances.


when wrapping dynamic components, inactive component instances are cached rather than destroyed.

As explained on the VUE website, we can use this in development to cache routing components that are backward without being refreshed. The specific implementation ideas are as follows.

1. Keep-alive is used in the template to cache the corresponding routing components


in app.vue template

<keep-alive> <router-view v-if="$route.meta.keepAlive"> <! </router-view> </keep-alive> <router-view v-if="! $route.meta.keepAlive"> <! </router-view> </router-view>Copy the code

This approach requires the coordination of the vUE routing meta information, which can also be done as follows:

<keep-alive include="A"> <router-view> <! Only view components whose paths match, as shown in listing A, are cached! --> </router-view> </keep-alive>Copy the code

Disadvantages of this approach are:

You need to know the **name** value of the routing component in advance, which is not a particularly good choice in large projects.Copy the code

2. Configure the route meta information in the route configuration file

The first template is used to expand the introduction. The configuration of the route metadata in the template file is as follows:

Routes: [{path: '/', name: 'home', Component: home, meta: {keepAlive: false // This component does not need to be cached}}, {path: '/list', name: 'list', Component: list, meta: {keepAlive: true // This component needs to be cached}}, {path: '/detail', name: 'detail', Component: Detail, meta: {keepAlive: false // This component needs to be cached}}]Copy the code

3. Provided in the Keep-alive componentactivatedThe hook function implements the data update logic

It is important to note that a keep-alive component is different from a VUE component. The specific lifecycle function of a VUE can be referred to here. The keep-alive component adds two additional keep-alive hook functions in addition to the normal vue component lifecycle:

  • Activated: triggered when the cached component enters again
  • Deactivated: Triggers when cached components depart

Since the Keep-alive component provides so many lifecycle hooks, what is the order in which these hook functions are executed?

When the keep-alive component is first entered, its lifecycle is executed in the following order:

beforeRouteEnter --> created --> mounted --> activated --> deactivatedCopy the code

Non-first-time entry, its life cycle execution sequence:

beforeRouteEnter -->activated --> deactivatedCopy the code

As you can see, the normal VUE component lifecycle functions will not be executed unless the keep-alive component is entered for the first time. Instead, the two new cycle hook functions added by keep-Alive will be executed. It can also be seen that the destroy cycle function is not executed when leaving the keep-alive component, which proves that the cache component is not destroyed. According to the introduction, we can:

The Use of keep-Alive provides the Activated hook function to determine whether ajax requests are made to update components, and the deactivated hook function to reset page-related state.

Keep-alive implements no refresh after push. There are some points that need to be noted:

  • Have a clear idea of when to update keep-alive components

This means that you need to know during development that you need to go back and not refresh components and not re-render them, but that you need to know when to re-send ajax requests to retrieve data and update components.

Take the above pages A and B for example, we need to know when the keep-alive component corresponding to page A of list A will be updated, because the entrance to page A can be backwards from page B or further from other pages. Of course, you need to distinguish between these two cases, otherwise the data on page A will always be the first cached data.

The article suggests a solution:

First, add an isBack field to each routing meta meta to resolve the fact that the beforeRouterEnter cannot access the Vue instance directly.

. {path: '/list', name: 'list', Component: list, meta: {keepAlive: true, // This component needs to be cached isBack: false}}...Copy the code

Then, use the beforeRouteEnter hook function to determine the page’s source:

BeforeRouteEnter (to, from, next) {if(from. Name === 'detail') { To.meta. IsBack = true; } next(); },Copy the code

Finally, we need to use keep-alive to provide the hook function activated to do this:

activated() { if(! This.$route.meta. IsBack) {this.getData() {this.getData(); $route. Meta. IsBack = false}; $route. Meta.Copy the code
  • The page refresh of the keep-alive component forward causes the keep-alive component status to be lost

Continue to page A and page B above as an example. After entering page B of details and refreshing, the cached data of page A of List A is lost. Due to the above judgment rules, data will not be obtained again. So for this kind of problem, we need to add some additional judgment conditions. Since keep-alive executes the created method the first time it enters, we use this to check with an identifier:

Created () {this.isFirstEnter = true; // Created () {this.isfirstEnter = true; }}}}}}}}}}}}}}}}}}}}Copy the code

The activated hook function also needs to add a corresponding judgment:

activated() { if(! This $route. The meta. IsBack | | this. IsFirstEnter) {/ / if isBack is false, show that need to get new data, otherwise no longer request, directly use the data/cache/if isFirstEnter is true, This.data = "// This. GetData (); } this.$route.meta. IsBack =false;} This. IsFirstEnter =false; },Copy the code
  • Too many keep-alive components are cached. Resident memory will cause too much memory usage

This is a special problem to pay attention to, especially when the whole system or most pages of the system use keep-alive to cache components, because they are cached in memory, if not processed, memory accumulation will become larger, resulting in system lag. The correct solution is to destroy the in-memory cached components in a timely manner.

For details, please refer to vue issue#6509 and remember the implementation ideas of the two articles of keep-alive trampling pit road of vue once.

Embedded routines by

Nesting routines by the specific implementation can refer to the official website, this scheme is also a solution. The following is a concrete example (as shown in the figure below) to illustrate the specific process of implementation.

Orders as shown above, a page out of the current page six to check the rule, agreement or change the content of some pages, because this 6 items depend on the order page, you can use nested routing to realize the back not refresh process, as the parent routing order page, other jump term can be used as its routing. Specific steps:

1. Configure routing information

    {
      path: '/order',
      component: Order,
      children: [
        {
          path: 'invoice',
          component: Invoice
        }, {
          path: 'contact',
          component: Contact
        },
        {
          path: 'costrule',
          component: CostRule
        }, {
          path: 'refundrule',
          component: RefundRule
        },{
          path: 'useragreement',
          component: UserAgreement
        },{
          path: 'payrule',
          component: PayRule
        }
      ]
    }Copy the code

2. On the single pageOrderConfigure route nesting in the component template.

    <div class="safe-area-pb">
     <purchase />
     <router-view />    
    </div>                  Copy the code

In this way, enter other pages through the order page, for example, enter the page for modifying contact information, then the route will enter /order/contact from /order. After the modification, the rollback will return to the parent route /order, and the function of pushing after completion will not be refreshed.

Of course, as mentioned above, nested routine scheme is only an optional scheme, with its corresponding use scenarios; In addition, the following points need to be paid attention to:

**1. After entering the child route, if the child route is forced to refresh, the components of the parent and child routes will be re-rendered, executing the life cycle of their own routing components; The setup logic in the parent route is executed.

**2, if the child route is shared by other pages, the first point will be triggered when entering the child route, so it is best that the child route is exclusive to the parent route.

Component works with the routing scheme

This scheme is mainly realized by using the dynamic routing component provided by VUE. The switching of page components is no longer determined by route path, but loads different dynamic components according to different business logic. See section 6 of this article’s solution: How do asynchronously loaded lines of business dynamically register routes? . In the same way, synchronous routes can also use dynamic routes to implement the corresponding backward without refreshing function. This is just a more limited way to use the scenario.

conclusion

Of the three solutions presented above, the first solution is familiar, while the latter two may be relatively unfamiliar. They’re just different solutions to the same problem, and presumably there are other solutions that I haven’t thought of, and better ones that we can discuss together.

reference

1. Didi WebApp 5.0 Vue 2.0 Refactoring Experience sharing Vue single page, multiple routes, forward refresh, backward not refresh 3, vue-router keep-alive 4, remember once vue keep-alive step on the pit 5, hope keep-alive can add the function that can dynamically delete cached components