简体   繁体   中英

Dynamic components based on route params in vue-router

Is it possible in Vue to dynamically use components based on the value of a route parameter?

Here's an example of what I'm trying to do:

path: '/model/:modelName',
components: {
  default: ModelDefinition.models.find((model) => model.key === $route.params.modelName),
},

The problem is: $route is not available here. Neither is modelName .

What might be nice if default could also be a function (similar to props ):

path: '/model/:modelName',
components: {
  default: (modelName) => (ModelDefinition.models.find((model) => model.key === $route.params.modelName)),
},

This function actually gets called to my surprise, but the argument seems to be some sort of function, and certainly not the modelName I'm hoping for.

The reason I need this is: there's actually a lot more configuration for this route, specifying lots of components and values for various things. If I have to specify that for every model, it's going to be long and repetitive, and would have to be expanded for every model we add to our system.

I'm not sure you have to "do magic" with vue-router - why don't you just handle the parameter inside your component (or create a container-component, and handle the parameter there)?

The snippet below shows that you can use external data to control what component should be displayed. If you pass your model parameter down, then any existing (and registered) component-name can be displayed.

 const CompA = { template: `<div class="border-blue">COMP-A</div>` } const CompB = { template: `<div class="border-red">COMP-B</div>` } new Vue({ el: "#app", components: { CompA, CompB }, data: { selected: '' } })
 [class^="border-"] { padding: 10px; } .border-blue { border: 1px solid blue; } .border-red { border: 1px solid red; }
 <script src="https://cdn.jsdelivr.net/npm/vue@2.x/dist/vue.js"></script> <div id="app"> <select v-model="selected"> <option disabled value="">Please select one</option> <option>CompA</option> <option>CompB</option> </select> <br /> <span>Selected: {{ selected }}</span> <br /> <br /> Here's a variable component - based on external data: <component :is="selected"></component> </div>

In components declaration, this is not available and hence you can not access the props and other instance data.

What you can do is create a computed property that returns a component. Like this:

<template>
  <component :is="componentInstance" />
</template>

<script>
export default {
  props: {
    componentName: String,
  },
  computed: {
    componentInstance() {
      return () => import(`./modules/${this.componentName}/template.vue`);
    },
  },
};
</script>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM