首页 > 解决方案 > 如果每个页面的 route/url 都会改变但 url 后面的 shell 仍然相同,如何使 vue router.js 文件动态化?

问题描述

如何使我的 vue 应用程序的 router.js 文件动态化。我正在尝试使用这个 vue-runtime-template-compiler 组件来实现动态渲染 - https://www.npmjs.com/package/vue-runtime-template-编译器。我这样做是为了避免为我的 vue 应用程序手动创建 vue 页面。相反,我现在使用更多元数据驱动的方法,每次我需要创建一个新页面时,我只需要基本上下载页面的元数据,动态渲染逻辑(SampleDynamicRendering.vue)将负责渲染实际页面.

SampleDynamicRendering.vue

<template>
  <div class="container is-fluid">
    <b-loading :is-full-page="true" :active.sync="this.isLoading"></b-loading>    
    <runtime-template-compiler :key="componentKey" :template="getUI"></runtime-template-compiler>
  </div>
</template>

<script>
import Vue from 'vue';
import { RuntimeTemplateCompiler } from "vue-runtime-template-compiler"
import { dynamicViewMixin } from "../../dynamicViewMixin.js";
const ViewName = "SampleDynamicRendering";
export default {
  name: "SampleDynamicRendering",
  mixins: [dynamicViewMixin()],
  data() {
    return {
      searchValue: '',
      data: [],      
        metadata: {
            "type": "page",
            "prop": {
              "api_id": 'api_actionlist',
              "api_path": '/action',
              "mounted_action": 'getDataArray',
              "before_action": 'setDataArray',
              "route_param": false,
              "init_obj": []
            },
            "children": [
              { "type": "title","label": "Actions" },
              {
                "type": "group",
                "children": [
                  {"type": "button", "label": "Add Action", "click": "$router.push({name: 'actionDetail', params:{id:null,masterdata:objectData}})"},
                  {
                    "type": "input", 
                    "value": "this.searchValue",
                    "placeholder": "search...",
                    "action": {
                      "input": "(newValue)=>{this.searchValue = newValue}"
                    }
                  },
                  {
                    "type": "table",
                    "data": "",
                    "columns": {

                    },
                    "action": {
                      "select": ""
                    }
                  }
                ]
              }
            ]
          }
    };
  },
  computed: {      
      getUI() {
          var tmplt_page  = (content) => {return `<div class="container is-fluid"><section class="section">${content}</section></div>`};
          var tmplt_cont  = (content) => {return `<div class="container is-fluid">${content}</div>`};
          var tmplt_title = (metadata) => {return `<h2 class="title">${metadata.label}</h2>`};
          var tmplt_input = (metadata) => {
            var p_label = typeof metadata.label != 'undefined' ? `label="${metadata.label}"` : '';
            var p_value = typeof metadata.value != 'undefined' ? `:value="${metadata.value}"`: '';
            var p_placeholder = typeof metadata.placeholder != 'undefined' ? `placeholder="${metadata.placeholder}"` : '';
            var p_action = typeof metadata.action != 'undefined' ? `@input="${metadata.action.input}"` : '';             
            return `<b-field ${p_label}><b-input ${p_value} ${p_action} ${p_placeholder}></b-input></b-field>`
          };
          var tmplt_buttn = (metadata) => {
            var p_label = typeof metadata.label != 'undefined' ? `${metadata.label}` : '';
            var p_click = typeof metadata.click != 'undefined' ? `@click="${metadata.click}"` : '';
            return `<b-field><b-button ${p_click} class="is-radiusless">${p_label}</b-button></b-field>`
          };
          var tmplt_table = (metadata) => {
            return `<b-table
          :data="filteredActionList"
          :paginated="true"
          :per-page="10"
          :columns="[{field: 'id', label: 'Action'},{field: 'description', label: 'Description'}]"
          selectable
          @select="selected"
        ></b-table>`;
          }

          var process = (metadata) => {
            var children = '';
            if (typeof metadata.children != 'undefined') {
              metadata.children.forEach((i) => {
                children = children + process(i);
              })
            }
            switch(metadata.type) {
              case 'title':
                return tmplt_title(metadata);
              case 'input':
                return tmplt_input(metadata);
              case 'button':
                return tmplt_buttn(metadata);
              case 'table':
                return tmplt_table(metadata);
              case 'page':
                return tmplt_page(children);
              case 'group':
                return tmplt_cont(children)
            }
          }

          return process(this.metadata);
      },
    filteredActionList () {
      if (this.objectData.length > 0) {
        return this.objectData.filter(option => {
          return (option.id + option.description)
            .toLowerCase()
            .includes(this.searchValue.toLowerCase())
        })
      } else {
        return this.objectData
      }
    }      
  },
  methods: {
    selected (item) {
      this.$router.push({ name: 'actionDetail', params: { id: item.id } })
    }
  },
  components: {
    RuntimeTemplateCompiler
  }
};
</script>

正如您在上面的代码中看到的,这是我目前用于动态渲染 vue 页面的方法。现在主要问题是,即使我将通过这个单个 vue 文件渲染所有页面,在一天结束时我仍然会有不同的路线在不同的页面之间导航。但目前每次有一个新页面时,我必须在 router.js 文件中为它创建一个新条目,如下所示 -

路由器.js

import Vue from 'vue'
import Router from 'vue-router'
import { compact } from 'lodash'

Vue.use(Router)

const createRouter = (routeData) => new Router({
    mode: 'history',
    base: process.env.BASE_URL,
    routes: routeData
})

const defaultRoutes = [{
    path: '/',
    name: 'home',
    component: () =>
        import('@/views/Home.vue'),
    props: false
},
{
    path: '/login',
    name: 'login',
    component: () =>
        import('@/views/Login.vue'),
    props: false
},
{
    path: '/employeeList',
    name: 'employeeList',
    component: () =>
        import('@/views/EmployeeList.vue'),
    props: false
},
{
    path: '/jobData',
    name: 'jobData',
    component: () =>
        import('@/views/JobData.vue'),
    props: false
},
{
    path: '/jobDetail',
    name: 'jobDetail',
    component: () =>
        import('@/views/JobDetail.vue'),
    props: false
},
{
    path: '/dev/sampleDynamicRendering',
    name: 'dev/sampleDynamicRendering',
    component: () => import('@/views/development/SampleDynamicRendering.vue'),
    props: false
},
]

const router = createRouter(defaultRoutes)

export function resetRouter() {
    const newRouter = createRouter(defaultRoutes)
    router.matcher = newRouter.matcher
}

export default router;

有什么办法可以让这个 router.js 文件也动态吗?如果每个页面的 url 都会改变,但在 url 后面它必须是相同的 shell(单页 vue 组件),我的选择是什么?

标签: vue.jsvue-componentvue-router

解决方案


推荐阅读