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

  1. 直接把这几个组件写在同一个组件下,通过v-if去判断。如果这么做的话,甚至可以不使用vue-router,直接把所有组件,都写在一个文件里面,全部通过v-if判断,也是可行的。(前提是几万行代码一起,你不嫌麻烦的话)
  2. 在渲染这个链接的时候,直接去请求后台的数据,通过数据渲染不同的链接。(理论上是可行的,但如果用户没有用这个功能,这些链接每次都提前取了后台数据;另外如果用户知道了链接,直接访问链接,还是需要逻辑去判断用户该看到哪个页面)
  3. 通过调用router.beforeEach,对每个路由进行拦截,当路由为我们指定的路由时,请求后台数据,动态跳转页面。(功能是可以完成,但实际上,这只是整个系统的一小块功能,不应该侵入整个路由系统,如果每个业务页面,都写在全局路由系统,也会导致路由的逻辑过于复杂)

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

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

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

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

  1. <!-- ChooseShopKPI.vue -->
  2. <template>
  3. <dataVersion v-if="!useNewShopKPI" />
  4. <ShopKPI v-else />
  5. </template>
  6. <script>
  7. import { get } from 'lodash';
  8. import { getStoreReportFormVersion } from '@/api/store';
  9. import dataVersion from './dataVersion';
  10. import ShopKPI from './ShopKPI';
  11. export default {
  12. name: 'ChooseShopKPI',
  13. components: {
  14. dataVersion,
  15. ShopKPI,
  16. },
  17. data() {
  18. return { useNewShopKPI: false };
  19. },
  20. created() {
  21. getStoreReportFormVersion().then((res) => {
  22. if (get(res, 'data.data.new')) {
  23. this.useNewShopKPI = true;
  24. }
  25. });
  26. },
  27. };
  28. </script>
  29. <style lang="css" scoped></style>

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

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

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

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

  1. 如果这种通过服务器加载数据的页面后续增加的话,会出现多个ChooseXXX的中间页面。
  2. 这种中间页面,实际上是做了二次路由,不熟悉逻辑的开发人员可能并不清楚这里面的页面跳转逻辑,增加了理解成本。

通过对ChooseXXX进行抽象,改造为DynamicLoadComponent

  1. <!-- DynamicLoadComponent.vue -->
  2. <template>
  3. <component :is="comp" />
  4. </template>
  5. <script>
  6. export default {
  7. name: 'DynamicLoadComponent',
  8. props: {
  9. renderComponent: {
  10. type: Promise,
  11. },
  12. },
  13. data() {
  14. return {
  15. comp: () => this.renderComponent
  16. }
  17. },
  18. mounted() {},
  19. };
  20. </script>
  21. <style lang="css" scoped></style>

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

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

  1. {
  2. path: 'shopKPI',
  3. component: () => import('@/views/store/components/DynamicLoadComponent'),
  4. name: 'store_KPI',
  5. menuName: '店铺参谋',
  6. meta: {
  7. codes: ['storeProduct:detail'],
  8. },
  9. props: (route) => ({
  10. renderComponent: new Promise((resolve, reject) => {
  11. getStoreReportFormVersion()
  12. .then((responseData) => {
  13. const useNewShopKPI = get(responseData, 'data.data.shop_do');
  14. const useOldShopKPI = get(
  15. responseData,
  16. 'data.data.store_data_show'
  17. );
  18. if (useNewShopKPI) {
  19. resolve(import('@/views/store/ShopKPI'));
  20. } else if (useOldShopKPI) {
  21. resolve(import('@/views/store/dataVersion'));
  22. } else {
  23. resolve(import('@/views/store/ShopKPI/NoKPIService'));
  24. }
  25. })
  26. .catch(reject);
  27. }),
  28. })
  29. }

版权声明:本文为zhea55原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://www.cnblogs.com/zhea55/p/15115555.html