【问题标题】:Dynamic components based on route params in vue-routervue-router中基于路由参数的动态组件
【发布时间】:2020-04-11 06:52:35
【问题描述】:

Vue 中是否可以根据路由参数的值动态使用组件?

这是我正在尝试做的一个示例:

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

问题是:$route 在此处不可用。 modelName 也不是。

如果default 也可以是一个函数(类似于props)会更好:

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

这个函数实际上被我惊讶地调用了,但参数似乎是某种函数,当然不是我希望的模型名称。

我需要这个的原因是:这条路线实际上有更多的配置,为各种事情指定了很多组件和值。如果我必须为每个模型指定它,这将是冗长且重复的,并且必须针对我们添加到系统中的每个模型进行扩展。

【问题讨论】:

  • 如何使用beforeEnter 导航守卫(或全局导航守卫)进行路由重定向?
  • 这似乎更多地用于重定向到其他路径,例如登录,而不是决定哪个组件需要在哪里呈现。或者你有这样使用它的例子吗?
  • 好吧,考虑到it's not yet created when the guard is called.因此,在 next 回调中传递“目标”路由可能会对您的情况有所帮助。

标签: vue.js vue-router


【解决方案1】:

我不确定你是否必须用 vue-router “做魔法” - 你为什么不只处理组件内部的参数(或创建一个容器组件,然后处理参数在那里)?

下面的sn-p显示你可以使用外部数据来控制应该显示什么组件。如果您向下传递 model 参数,则可以显示任何现有(和已注册的)组件名称。

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>

【讨论】:

  • 这个例子没有使用路由器,但是使用一个只解释路由参数然后加载正确组件的包装器组件可能会起作用,是的。唯一的缺点是我将到处使用这些容器组件。我希望将它全部保存在一个地方:路由器。但这会奏效。谢谢。
  • 也许你可以将这个“容器”创建为一个 mixin,并在全局范围内导入它——这可能是一种不明智的方法,但在技术上是可行的(这只是一个自发的想法,没有经过测试或思考它通过)
【解决方案2】:

components 声明中,this 不可用,因此您无法访问道具和其他实例数据。

您可以做的是创建一个返回组件的计算属性。像这样:

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

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

【讨论】:

    猜你喜欢
    • 2017-06-20
    • 1970-01-01
    • 2020-07-19
    • 2017-07-17
    • 2019-12-19
    • 2021-09-29
    • 1970-01-01
    • 2021-05-18
    • 2021-06-05
    相关资源
    最近更新 更多