是否可以使用for循环内部函数生成vue组件?

时间:2019-06-20 08:14:01

标签: vue.js

可以使用for循环生成vue组件。我正在尝试生成并能够获取,但是它被新组件动态覆盖,它最终覆盖了组件一个架构,组件第二个组件也最终生成了。

https://jsfiddle.net/3ordn7sj/5/ https://jsfiddle.net/bt5dhqtf/973/

for (var key  in app.html) {
        Vue.component(key, {
        template: `<div><vue-form-generator :model="model"
        :schema="schema"
        :options="formOptions"
        ref="key"></vue-form-generator>{{ key }}</div>`,
        mounted() {
          this.schema = app.html[key]
        },
        data: function () {
          return {
            schema: app.html[key],
            key: '',
            formOptions: this.formOptions,
            model: this.model,
          }
        },
      }
    )
    }

可以使用for循环生成vue组件。我正在尝试生成并能够获取,但是它被新组件动态覆盖,它最终覆盖了组件一个架构,组件第二个组件也已生成。在上面的jsfiddel链接中,我的数据在其中创建。

我正在尝试基于此数据生成vue组件,并且正在使用vue表单生成器。在上面的代码中,我真正想做的是在我的循环运行表单生成时,但我也不知道它也是第一个组件获取第二个组件架构及其在第一步显示的内容也会覆盖架构数据。

我很困惑为什么会发生这种情况,我尝试了很多,但是如果您有任何建议,请提出我可以使用for内部循环函数生成组件的方法。

请尝试解决此问题或告诉我它;不可能。

我确实喜欢

<form-wizard @on-complete="onComplete"
                     @on-change="handleChange"
                     validate-on-back
                     ref="wizard"
                     :start-index.sync="activeTabIndex"
                     shape="circle" color="#20a0ff" error-color="#ff4949" v-if="html != 0">
            <tab-content v-for="tab in tabs"
                         v-if="!tab.hide"
                         :key="tab.title"
                         :title="tab.title"
                         :icon="tab.icon">
                <component :is="tab.component"></component>
            </tab-content>
        </form-wizard>

我现在为此选项卡选项添加的内部数据

tabs: [{title: 'Personal details', icon: 'ti-user', component: 'firstTabSchema'},
                    {title: 'Is Logged In?', icon: 'ti-settings', component: 'secondTabSchema', hide: false},
                ],

generateNewForm.vue

<template>
    <div class="app animated fadeIn">
        <loading :active.sync="this.$store.state.isLoading"
                 :can-cancel="true"
                 :is-full-page="this.$store.state.fullPage"></loading>
        <b-row>
            <b-col cols="12" xl="12">
                <transition name="slide">
                    <b-card>
                        <div slot="header">
                            <b-button variant="primary" @click="goBack"><i class="icon-arrow-left icons font-1xl"></i>Back</b-button>
                        </div>

                        <formcomponent  :tree="this.$store.state.formData" />
                    </b-card>
                </transition>
            </b-col>
        </b-row>
    </div>
</template>
<script>
    import {store} from '@/components/store'
    import formcomponent from '@/components/formcomponent';
    import Vue from 'vue'
    import Loading from 'vue-loading-overlay';
    import 'vue-loading-overlay/dist/vue-loading.css';
    import {FormWizard, TabContent} from 'vue-form-wizard'
    import 'vue-form-wizard/dist/vue-form-wizard.min.css'
    import VueFormGenerator from "vue-form-generator";
    /*import VeeValidate from 'vee-validate';*/
    Vue.use(VueFormGenerator);
    Vue.use(Loading);

    export default {
        name: 'tables',
        store: store,
        data: () => {
            return {
                finalModel: {},
                activeTabIndex: 0,
                model: {},
                count: 0,
            }
        },
        components: {
            'loading': Loading,
            FormWizard,
            TabContent,
            formcomponent: formcomponent
        },

        created() {

        },
        beforeMount() {
            this.$store.dispatch('loadFormData', this.$route.params.id);
        },
        methods: {
            onComplete: function(){
                alert('Yay. Done!');
            },
            goBack() {
                this.$router.go(-1)
            }
        }
    }
</script>

formcomponent.vue

<template>
    <div>
        <form-wizard @on-complete="onComplete"
                     @on-change="handleChange"
                     validate-on-back
                     ref="wizard"
                     :start-index.sync="activeTabIndex"
                     shape="circle" color="#20a0ff" error-color="#ff4949" v-if="html != 0">
            <tab-content v-for="tab in tabs"
                         v-if="!tab.hide"
                         :key="tab.title"
                         :title="tab.title"
                         :icon="tab.icon">
                <component :is="tab.component"></component>
            </tab-content>
        </form-wizard>

    </div>
</template>

<script>
    import Vue from 'vue'
    import {FormWizard, TabContent} from 'vue-form-wizard'
    import 'vue-form-wizard/dist/vue-form-wizard.min.css'
    import VueFormGenerator from "vue-form-generator";

    //console.log(Vue.options);
    Vue.use(VueFormGenerator);
    export default {
        components: {
            FormWizard,
            TabContent,
        },
        data() {
            return {
                loadingWizard: false,
                error: null,
                count: 0,
                dash: '-',
                firstTime: 0,
                model: {},
                html: '',
                index: '',
                activeTabIndex: 0,
                tabs: [{title: 'Personal details', icon: 'ti-user', component: 'firstTabSchema'},
                    {title: 'Is Logged In?', icon: 'ti-settings', component: 'secondTabSchema', hide: false},
                ],
                formOptions: {
                    validationErrorClass: "has-error",
                    validationSuccessClass: "has-success",
                    validateAfterLoad: true,
                    validateAfterChanged: true,
                },
            }
        },
        created() {
            this.html = this.tree;
            this.index = this.ind;
        },
        props: ['tree', 'ind'],
        methods: {
            onComplete: function () {
                alert('Yay. Done!');
            },
            setLoading(value) {
                this.loadingWizard = value
            },
            handleChange(prevIndex, nextIndex) {
                console.log(`Changing from ${prevIndex} to ${nextIndex}`)
            },
            setError(error) {
                this.error = error
            },
            validateFunction: function () {

                return new Promise((resolve, reject) => {
                    console.log(this.$refs.firstTabSchema);
                    setTimeout(() => {
                        if (this.count % 2 === 0) {
                            reject('Some custom error')
                        } else {
                            resolve(true)
                        }
                        this.count++
                    }, 100)
                })
            },
            validate() {
                return true
            },
            buildTree(tree, rep = 1) {
                var html = '';
                var app = this;
                var dash = "--";
                app.html = tree;

                var test = this.formOptions;


                for (var key  in app.html) {
                    var isComponentExists = key in Vue.options.components
                    if(!isComponentExists) {
                    Vue.component(key, {
                            template: `<div :class="key"><vue-form-generator :model="model"
                                            :schema="schema"
                                            :options="formOptions"
                                            ref="key"></vue-form-generator>{{ key }}</div>`,
                            mounted() {
                               this.schema = app.html[key]
                               this.key = key
                            },
                            data: function () {
                                return {
                                    schema: app.html[key],
                                    key: '',
                                    formOptions: this.formOptions,
                                    model: this.model,
                                }
                            },
                        }
                    )
                    //console.log(Vue.$options);
                    this.$emit('init')
                    }
                }
            }
        },
        watch: {
            tree: {
                handler() {
                    this.html = '';
                    this.buildTree(this.tree)
                },
                deep: true
            }
        }
    }

</script>

2 个答案:

答案 0 :(得分:1)

因此,如果我对您的理解正确,那么您正在尝试使用某种类型的列表app.html动态注册一组使用不同名称(key)的相同组件。我认为这是可能的,但我无法从您提供的代码中看出问题所在。

我可以告诉您,这种代码重用/抽象的方法可能不是正确的方法。组件的全部目的是您可以通过使用绑定道具来重用功能。您正在尝试做的事情可能会像这样更好地实现:

 Vue.component('my-custom-form', {
        props: ['key', 'schema', 'formOptions', 'model'],
        template: `
            <div>
              <vue-form-generator 
                :model="model"
                :schema="schema"
                :options="formOptions"
                :ref="key"
              ></vue-form-generator>{{ key }}
            </div>`,

})

然后在您的Vue模板中:

<my-custom-form
  v-for="(key, value) in app.html"
  :key="key"
  :schema="value"
  :formOptions="formOptions"
  :model="model"
/>

让我知道是否有帮助。否则,如果您确定要坚持使用原始方法,请为我​​提供更多代码上下文,然后我会做些什么。祝你好运!

答案 1 :(得分:0)

我想我对您遇到的困难了解得更多。我在您的jsfiddle中看到了这段代码:

<div id="app">
<div>
  <form-wizard @on-complete="onComplete">
    <tab-content v-for="tab in tabs"
                v-if="!tab.hide"
                :key="tab.title"
                :title="tab.title"
                :icon="tab.icon">
      <component :is="tab.component"></component>
    </tab-content>
  </form-wizard>
 </div>
</div>

您无需使用component :is语法即可解决此问题。您还可以编写如下:

<div id="app">
<div>
  <form-wizard @on-complete="onComplete">
    <tab-content v-for="(tab, tabindex) in tabs"
                v-if="!tab.hide"
                :key="tab.title"
                :title="tab.title"
                :icon="tab.icon">
      <my-custom-form v-if="tabindex == 1" :key="'the first key'" :schema="app.html['the first key']"/>
      <my-custom-form v-else-if="tabindex == 2" :key="'the second key'" :schema="app.html['the second key']"/>
    </tab-content>
  </form-wizard>
 </div>
</div>

等让我知道那个例子是否清楚。 最好