当前位置:主页 > 网页前端 > vue >

Vue Router根据后台数据加载不同的组件实现

时间:2022-06-21 10:01:08 | 栏目:vue | 点击:

实际项目中遇到的需求

同一个链接需要加载不同的页面组件。根据用户所购买服务的不同,有不同的页面展现。

有一些不好的实现方式

个人感觉比较好的实现方式

在配置路由的地方获取服务器数据动态加载对应的组件

{
  path: 'shopKPI',
  // 如果提前把后台数据存到store里面,在这里访问store数据,可以直接判断出来
  // 但这种特定业务页面的数据放全局store,其他地方也不用,实在没有必要
  component: () => import('@/views/store/dataVersion'),
  name: 'store_KPI',
  menuName: '店铺参谋',
  meta: {
    codes: ['storeProduct.detail']
  }
}

理想很美好,现实的情况是,component接收的这个方法必须要同步的返回一个promise。

这时候我想到了上面不好的实现方式1,稍微加以改造

<!-- 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>

把路由渲染对应的页面,改为渲染这个中间页面ChooseShopKPI

{
  path: 'shopKPI',
  // 如果提前把后台数据取到,在这里访问store数据,可以直接判断出来
  // 但这种特定业务页面的数据放全局store,其他地方也不用,实在没有必要
-  component: () => import('@/views/store/dataVersion'),
+  component: () => import('@/views/store/ChooseShopKPI'),
  name: 'store_KPI',
  menuName: '店铺参谋',
  meta: {
    codes: ['storeProduct.detail']
  }
}

这样就实现了我们期望的功能。

功能已实现,但我又开始了新的思考

这种方式虽然很好的解决了动态加载页面组件的问题。但也产生了一些小问题。

最终方案――高阶组件

通过对ChooseXXX进行抽象,改造为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>

直接在路由的配置中获取后台数据,并进行路由的分发。这样路由逻辑都集中在路由配置文件中,没有二次路由。维护起来不会头疼脑胀。

DynamicLoadComponent组件也得以复用,后续新增判断后台数据加载页面的路由配置,都可以导向这个中间组件。

{
  path: 'shopKPI',
  component: () => import('@/views/store/components/DynamicLoadComponent'),
  name: 'store_KPI',
  menuName: '店铺参谋',
  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);
    }),
  })
}

查看在线小例子(只支持chrome)
https://stackblitz.com/edit/vuejs-starter-jsefwq?file=index.js

您可能感兴趣的文章:

相关文章