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

Web Design Tutorial (3): Design Steps and Thinking

<br />Previous tutorial: Web Design Tutorial...

Data Structure - Tree (III): Multi-way Search Tree B-tree, B+ tree

Multi-way search tree Height of a complete binary...

Summary of the advantages of Vue3 vs. Vue2

Table of contents 1. Why do we need vue3? 2. Adva...

Detailed explanation of Nginx's control over access volume

Purpose Understand the Nginx ngx_http_limit_conn_...

Causes and solutions for MySQL master-slave synchronization delay

For historical reasons, MySQL replication is base...

In-depth understanding of Worker threads in Node.js

Table of contents Overview The history of CPU-bou...

Learning about UDP in Linux

Table of contents 1. Introduction to UDP and Linu...

Detailed explanation of zabbix executing scripts or instructions on remote hosts

Scenario Requirements 1. We can use the script fu...

How to use Javascript to generate smooth curves

Table of contents Preface Introduction to Bezier ...

Summary of constructor and super knowledge points in react components

1. Some tips on classes declared with class in re...

How to quickly build an LNMP environment with Docker (latest)

Preface Tip: Here you can add the approximate con...

A Brief Discussion on the Navigation Window in Iframe Web Pages

A Brief Discussion on the Navigation Window in If...