Vue Router loads different components according to background data

Vue Router loads different components according to background data

Requirements encountered in actual projects

The same link needs to load different page components. Different pages are displayed depending on the services purchased by the user.

There are some bad implementations

  • Simply write these components under the same component and judge them through v-if. If you do this, you don't even need to use vue-router. You can just write all the components in one file and use v-if to judge them all. (The premise is that there are tens of thousands of lines of code together, if you don't mind the trouble)
  • When rendering this link, directly request the background data and render different links based on the data. (It is theoretically feasible, but if the user does not use this function, these links will fetch the background data in advance each time; in addition, if the user knows the link and directly accesses the link, logic is still needed to determine which page the user should see)
  • By calling router.beforeEach, each route is intercepted. When the route is the route we specify, the background data is requested and the page is jumped dynamically. (The function can be completed, but in fact, this is only a small part of the entire system and should not invade the entire routing system. If each business page is written in the global routing system, it will also cause the routing logic to be too complicated.)

I personally feel that the better way to implement

Get server data where the route is configured and dynamically load the corresponding components

{
  path: 'shopKPI',
  // If you save the background data to the store in advance, you can directly judge it by accessing the store data here // But the data of this specific business page is placed in the global store and is not used anywhere else, so it is really unnecessary component: () => import('@/views/store/dataVersion'),
  name: 'store_KPI',
  menuName: 'Shop Consultant',
  meta: {
    codes: ['storeProduct.detail']
  }
}

The ideal is beautiful, but the reality is that the method received by the component must return a promise synchronously.

At this time, I thought of the bad implementation method 1 above and modified it slightly.

<!-- ChooseShopKPI.vue -->
<template>
  <dataVersion v-if="!useNewShopKPI" />
  <ShopKPI v-else />
</template>

<script>
import { get } from 'lodash';
import { getStoreReportFormVersion } from '@/api/store';
import dataVersion from './dataVersion';
import ShopKPI from './ShopKPI';

export default {
  name: 'ChooseShopKPI',

  components:
    dataVersion,
    ShopKPI,
  },

  data() {
    return { useNewShopKPI: false };
  },

  created() {
    getStoreReportFormVersion().then((res) => {
      if (get(res, 'data.data.new')) {
        this.useNewShopKPI = true;
      }
    });
  },
};
</script>

<style lang="css" scoped></style>

Change the page corresponding to the route rendering to render this intermediate page ChooseShopKPI

{
  path: 'shopKPI',
  // If you get the background data in advance, you can directly judge it by accessing the store data here // But the data of this specific business page is placed in the global store and is not used anywhere else, so it is really unnecessary - component: () => import('@/views/store/dataVersion'),
+ component: () => import('@/views/store/ChooseShopKPI'),
  name: 'store_KPI',
  menuName: 'Shop Consultant',
  meta: {
    codes: ['storeProduct.detail']
  }
}

This achieves the functionality we expect.

The function has been realized, but I started to think about it again

Although this method solves the problem of dynamically loading page components very well. But some minor problems also arose.

  • If more pages that load data through the server are added later, multiple ChooseXXX intermediate pages will appear.
  • This kind of intermediate page actually performs secondary routing. Developers who are not familiar with the logic may not be clear about the page jump logic here, which increases the cost of understanding.

The final solution - high-level components

By abstracting ChooseXXX, transform it into DynamicLoadComponent

<!-- DynamicLoadComponent.vue -->
<template>
  <component :is="comp" />
</template>

<script>
export default {
  name: 'DynamicLoadComponent',
  props: {
    renderComponent: {
      type: Promise,
    },
  },
  data() {
    return {
      comp: () => this.renderComponent
    }
  },
  mounted() {},
};
</script>

<style lang="css" scoped></style>

Get the background data directly in the routing configuration and distribute the routes. In this way, the routing logic is concentrated in the routing configuration file, and there is no secondary routing. Maintenance won’t be a headache.

The DynamicLoadComponent component can also be reused, and any subsequent routing configurations for determining the background data loading page can be directed to this intermediate component.

{
  path: 'shopKPI',
  component: () => import('@/views/store/components/DynamicLoadComponent'),
  name: 'store_KPI',
  menuName: 'Shop Consultant',
  meta: {
    codes: ['storeProduct:detail'],
  },
  props: (route) => ({
    renderComponent: new Promise((resolve, reject) => {
      getStoreReportFormVersion()
        .then((responseData) => {
          const useNewShopKPI = get(responseData, 'data.data.shop_do');
          const useOldShopKPI = get(
            responseData,
            'data.data.store_data_show'
          );

          if (useNewShopKPI) {
            resolve(import('@/views/store/ShopKPI'));
          } else if (useOldShopKPI) {
            resolve(import('@/views/store/dataVersion'));
          } else {
            resolve(import('@/views/store/ShopKPI/NoKPIService'));
          }
        })
        .catch(reject);
    }),
  })
}

View online example (only supports Chrome)
https://stackblitz.com/edit/vuejs-starter-jsefwq?file=index.js

This is the end of this article about Vue Router loading different components according to background data. For more information about Vue Router loading different components according to background data, please search for previous articles on 123WORDPRESS.COM or continue to browse the following related articles. I hope you will support 123WORDPRESS.COM in the future!

You may also be interested in:
  • Detailed explanation of vue-router data loading and cache usage summary

<<:  Solution to ERROR 1054 (42S22) when changing password in MySQL 5.7

>>:  Detailed explanation of permission management commands in Linux (chmod/chown/chgrp/unmask)

Recommend

How to export mysql table structure to excel

The requirements are as follows Export the table ...

Solve the problem of setting Chinese language pack for Docker container

If you use docker search centos in Docker Use doc...

Eight ways to implement communication in Vue

Table of contents 1. Component Communication 1. P...

HTML framework_Powernode Java Academy

1. Framework A browser document window can only d...

The past two years with user experience

<br />It has been no more than two years sin...

MySQL 5.7.17 installation and configuration tutorial for Mac

1. Download MySQL Click on the official website d...

How to install mysql database in deepin 2014 system

Deepin 2014 download and installation For downloa...

H tags should be used reasonably in web page production

HTML tags have special tags to handle the title of...

How to configure environment variables in Linux environment

JDK download address: http://www.oracle.com/techn...

The best way to solve the 1px border on mobile devices (recommended)

When developing for mobile devices, you often enc...

Detailed explanation of the difference between docker-compose ports and expose

There are two ways to expose container ports in d...

Summary of some practical little magic in Vue practice

How can you forget lazy loading of routes that al...

Guide to Efficient Use of MySQL Indexes

Preface I believe most people have used MySQL and...