【问题标题】:Using Vue :is prop for dynamic components passed via config object对通过配置对象传递的动态组件使用 Vue :is prop
【发布时间】:2019-06-17 16:17:08
【问题描述】:

我有一个带有如下配置对象的确认弹出 Vue 组件:

{
  title: null,
  message: null,
  onConfirm: null,
  onDismiss: null,
  modal_class: null,
  icon: null,
  confirmBtnText: null,
  confirmBtnColor: null,
  component: null
}

在模板中,我想在这里呈现一个“动态”组件:

<component class="component-container" :is="component"></component>

我正在初始化传入的组件,如下所示:

import {CarrierSaferInfo} from './path/to/single-file-component.vue'
let SaferInfo = Vue.extend(CarrierSaferInfo)
let SaferComp = new SaferInfo({
  propsData: {
    carrier,
    dom_class: 'text-white',
  }
})
openConfirmDialog({
  //...other props
  component: SaferComp
})

但我得到了错误:

Failed to mount component: template or render function not defined.

编辑: 我现在尝试使用组件的实际 $options 对象,如下所示:

<component class="component-container" :is="component.$options"></component>

在组件定义中,prop carrier 是必需的。事件虽然在$options 对象中显示carrier 中的propsData 道具是一个对象,但它仍然在说:

Missing required prop: carrier

所以,取得了进展,但现在 propsData 由于某种原因没有填充到渲染函数中。

【问题讨论】:

  • 我不认为你可以将 'is' 属性绑定到 div 元素...你试过这个:
  • @SirDad 我刚刚尝试过,它给出了同样的错误
  • 我不熟悉你初始化它的方式,但:is 需要string 所以:is='SaferInfo'
  • @SatyamPathak 我以这种方式初始化组件的原因是因为每次初始化组件时都需要更改道具。从文档中,:is 属性将采用名称(您的建议)或组件选项对象(对于我的示例来说是必需的)

标签: vue.js


【解决方案1】:

我认为您正在寻找v-bind 而不是is。如果您想将其全部保留为一个对象,您可以在 v-bind 中包含 is

const CarrierSaferInfo = {
  props: {
    dom_class: String,

    carrier: {
      required: true,
      type: String
    }
  },

  template: '<div :class="dom_class">{{ carrier }}</div>'
}

new Vue({
  el: '#app',

  data() {
    return {
      component: null
    }
  },

  methods: {
    onClick() {
      this.component = {
        is: CarrierSaferInfo,
        carrier: 'hello',
        dom_class: 'text-white'
      }
    }
  }
})
<script src="https://unpkg.com/vue@2.6.10/dist/vue.js"></script>
<div id="app">
  <button @click="onClick">Open</button>
  <component v-if="component" v-bind="component" />
</div>

值得注意的是,我已经删除了SaferInfoSaferComp 以及任何提及Vue.extendnew。在我有 this.component = ... 的地方,你可能需要使用类似的东西:

openConfirmDialog({
    // ... other props ...
    component: {
        is: CarrierSaferInfo,
        carrier,
        dom_class: 'text-white'
    }
})

它可以与is一起工作。不确定是否有更直接的方法来执行此操作,但包装器组件可以提供设置道具的render 函数。例如:

const CarrierSaferInfo = {
  props: {
    dom_class: String,

    carrier: {
      required: true,
      type: String
    }
  },

  template: '<div :class="dom_class">{{ carrier }}</div>'
}

new Vue({
  el: '#app',

  data() {
    return {
      component: null
    }
  },

  methods: {
    onClick() {
      this.component = {
        render(h) {
          return h(CarrierSaferInfo, {
            props: {
              carrier: 'howdy',
              dom_class: 'text-white'
            }
          })
        }
      }
    }
  }
})
<script src="https://unpkg.com/vue@2.6.10/dist/vue.js"></script>
<div id="app">
  <button @click="onClick">Open</button>
  <component v-if="component" :is="component" />
</div>

【讨论】:

  • 是的!这工作得很好......不知道为什么在文档的动态组件部分没有提到它。我刚刚做了&lt;component v-if="component" v-bind="component" /&gt;
  • 忽略最后的评论 - 它没有用。我需要这个:&lt;component :is="component.$options" v-bind="component.$options.propsData" /&gt;
  • @MikeHarrison 这表明你仍然在找错树。您不需要去$optionspropsData 附近的任何地方。我在第一个示例下方添加了更多解释,以尝试阐明它如何应用于您的场景。
  • 感谢@skirtle - 我已将其更改为&lt;component :is="component" v-bind="componentProps" /&gt;,并为openConfirmDialog() 提供了另一个配置选项
【解决方案2】:

这看起来很相关:https://top10webjs.com/2019/02/02/vue-js-passing-props-dynamically-to-dynamic-component-in-vuejs/

<component :is=”currentComponent” v-bind=”currentProperties”></component>

通过这里的语法: https://vuejs.org/v2/guide/components-props.html#Passing-the-Properties-of-an-Object

【讨论】:

    猜你喜欢
    • 2021-08-26
    • 2023-03-15
    • 2020-11-15
    • 1970-01-01
    • 2020-02-07
    • 2022-01-20
    • 2019-04-03
    • 2021-12-24
    • 2018-07-09
    相关资源
    最近更新 更多