是否可以创建Vue组件以动态呈现全局组件列表?

时间:2019-10-07 19:58:55

标签: vue.js

当用户将其拖放到布局编辑器上时,我将在UI上列出并渲染一些全局注册的基本组件。然后,我希望在<ComponentRenderer/>组件上对其进行处理。

<ComponentRenderer/>内,我目前有这种逻辑:

<template>
    <div class="component-renderer">
        <radio-button
            :pageId="pageId"
            :input="input"
            :preview="preview"
            v-if="input.type == 'radio'"
        ></radio-button>

        <check-box
            :pageId="pageId"
            :input="input"
            :preview="preview"
            v-if="input.type == 'checkbox'"
        ></check-box>

        <standard-input
            :pageId="pageId"
            :input="input"
            :preview="preview"
            v-if="input.type == 'input'"
        ></standard-input>

        ...
        ...
    </div>
</template>

现在,我不是希望使用v-if对其进行硬编码和手动比较,而是希望它动态地进行自我比较并呈现其元素和属性,以便在使用新组件时无需注册其他组件。添加。看起来像这样:

<template>
  <div class="component-renderer" v-html="preRenderComponent"></div>
</template>

<script>
  export default {
    props: {
      targetedComponent: {
        type: Object,
        required: true
      }
    },
    computed: {
      preRenderComponent() {
        return this.$options.components.filter(
          component =>
            component.extendOptions.name.toLowerCase() == "base" + this.targetedComponent.type.toLowerCase() // E.g: 'input'
        );
      }
    }
  };
</script>

有可能吗?如果可能的话,我该如何渲染元素和属性?知道当我做console.log(Vue.options.components)并进行探索时,它并没有提供要呈现的元素。

1 个答案:

答案 0 :(得分:0)

首先,我要感谢Steven Spungin&Phil提供有关此问题的信息。

我试图在我的代码上实现它,并且它确实按预期工作。对于任何想知道它是什么样的人,我在这里提供已经实现的代码。

LayoutRenderer.vue

<template>
  <GridLayout
    v-if="pageComponents.length != 0"
    :layout.sync="pageComponents"
    :col-num="12"
    :row-height="30"
    :is-draggable="true"
    :is-resizable="true"
    :is-mirrored="false"
    :vertical-compact="true"
    :margin="[10, 10]"
    :use-css-transforms="true"
    :responsive="true"
    :auto-size="true"
  >
    <GridItem
      v-for="component in pageComponents"
      :key="component.i"
      :x="component.x"
      :y="component.y"
      :w="component.w"
      :h="component.h"
      :i="component.i"
    >
      <!-- <ComponentRenderer :component="component"></ComponentRenderer> -->
      <Component :is="named(component)"></Component>
    </GridItem>
  </GridLayout>
</template>

<script>
  import VueGridLayout from "vue-grid-layout";
  export default {
    components: {
      GridLayout: VueGridLayout.GridLayout,
      GridItem: VueGridLayout.GridItem
    },
    data() {
      return {
        pageComponents: []
      };
    },
    created() {
      this.fetchComponents();
    },
    methods: {
      fetchComponents() {
        let pageId = this.$route.params.component.pageId;

        this.$store.dispatch("components/fetchComponents", pageId).then(() => {
          this.pageComponents = this.$store.getters["components/components"];
        });
      },
      named(component) {
        let componentName = this.$options.filters.capitalize(component.type);
        return `Base${componentName}`;
      }
    }
  };
</script>