0

我在理解递归组件时遇到了一些麻烦,我相信对于我想要完成的事情,这可能是最好的方法。这是到目前为止我所处的位置的小提琴,将在下面解释。

https://jsfiddle.net/wp0hon7z/2/

我试图遍历一个嵌套的 JSON,它本质上模仿了一个 DOM。每个“节点”看起来像这样。您可以打开小提琴以查看更多嵌套的 JSON 和

"tagName": "section",
"classes": ["container", "mx-auto"],
"attrs": {"id":"main"},
"textNode": "",
"children": [{}]

目前我能够递归地遍历并将每个节点创建到一个组件中,并将它们放入一个组件数组中,我在 Vue 实例中填充该数组。

问题是,子组件需要显示在父组件内。我在想也许用组件对象创建一个对象,然后使用递归组件来解析这些,但我不知道该怎么做。

另一个想法可能是创建一个带有父 ID 的平面组件数组?然后可能以某种方式使用它?

关于如何去做的一些指导会很棒,我认为递归组件会有所帮助,但不确定除了创建元素/渲染函数之外我还能如何使用它。每个节点都需要与类列表、属性列表、on 等进行 2 路绑定。我计划跟踪这些并使用状态/存储进行编辑,可能是 vuex。

目前在 Fiddle 中看到的代码将显示 JSON 中的所有组件,但没有嵌套,所以只是一个接一个。

    const jsonData = [
        {
            "tagName": "section",
            "classes": ["container","mx-auto"],
            "attrs": {},
            "textNode": "",
            "children": [
                {
                   "tagName": "div",
                    "classes": ["flex","flex-wrap"],
                    "attrs": {},
                    "textNode": "",
                    "children": [
                        {
                            "tagName": "div",
                            "classes": ["w-1/2"],
                            "attrs": {},
                            "textNode": "Hello"
                        },
                        {
                            "tagName": "div",
                            "classes": ["w-1/2"],
                            "attrs": {},
                            "textNode": "Goodbye"
                        }
                    ]
                }
            ]
        }
    ];



    let Components = [];
    let uuid = 0;
 

    function recurse() { 
            recursiveInitialize(jsonData)
      
    }

 function recursiveInitialize(j) {

        
        if (Array.isArray(j)) {
            return j.map((child) => recursiveInitialize(child))
        }

        if (j.children && j.children.length > 0) {


             initializeComponent(j)

            console.log("Hi I am " + j["tagName"] + " and a parent")


            j.children.forEach((c) => {
                console.log("Hi I am " + c["tagName"] + " and my parent is " + j["tagName"])
                recursiveInitialize(c)
            });


        }

        else {
            console.log("Hi, I dont have any kids, I am " + j["tagName"])
            initializeComponent(j)
        }
    }
    

  function initializeComponent(jsonBlock){
        let tempComponent = {
        		name: jsonBlock["tagName"]+ uuid.toString(),
            methods: {
                greet() {
                    store.setMessageAction(this)
                }
              },
            data: function() {
                return {
                    tagName: jsonBlock["tagName"],
                    classes: jsonBlock["classes"],
                    attrs: jsonBlock["attrs"],
                    children: jsonBlock["children"],
                    textNode: jsonBlock["textNode"],
                    on: {click: this.greet},
                    ref: uuid,
                }
            },
            beforeCreate() {
                this.uuid = uuid.toString();
                uuid += 1; 
                
            
            },
            render: function(createElement) {
                  return createElement(this.tagName, {
                    class: this.classes,
                    on: {
                        click: this.greet
                    },
                    attrs: this.attrs,
                }, this.textNode);
            },
            mounted() {
                // example usage
                console.log('This ID:', this.uuid);
            },
        }
        Components.push(tempComponent);
        return tempComponent
    }
 
    const App = new Vue({
        el: '#app',

        data: {
            children: [
                Components
            ],
        },
        beforeCreate() {
            recurse();
            console.log("recurseRan")
        },

        mounted() {
            this.populate()
        },

        methods: {
            populate() {
                let i = 0;
                let numberOfItems = Components.length;

                for (i = 0; i < numberOfItems; i++) {
                    console.log("populate: " + Components[i])
                    this.children.push(Components[i]);
                }

            },
        }
    });
 
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>


                        <div id="app">
                            <template v-for="(child, index) in children">
                                <component :is="child" :key="child.name"></component>
                            </template>
                        </div> 

4

2 回答 2

0

您是否尝试过按照以下方式做一些事情

// MyRecursiveComponent.vue
<template>
  <div>
    <!-- node content -->
    <div v-for="childNode" in jsonData.children">
      <MyRecursiveComponent :jsonData="childNode" />
    </div>
  </div>
<template
于 2020-05-24T22:41:08.843 回答
-2

    const jsonData = [
        {
            "tagName": "section",
            "classes": ["container","mx-auto"],
            "attrs": {},
            "textNode": "",
            "children": [
                {
                   "tagName": "div",
                    "classes": ["flex","flex-wrap"],
                    "attrs": {},
                    "textNode": "",
                    "children": [
                        {
                            "tagName": "div",
                            "classes": ["w-1/2"],
                            "attrs": {},
                            "textNode": "Hello"
                        },
                        {
                            "tagName": "div",
                            "classes": ["w-1/2"],
                            "attrs": {},
                            "textNode": "Goodbye"
                        }
                    ]
                }
            ]
        }
    ];



    let Components = [];
    let uuid = 0;
 

    function recurse() { 
            recursiveInitialize(jsonData)
      
    }

 function recursiveInitialize(j) {

        
        if (Array.isArray(j)) {
            return j.map((child) => recursiveInitialize(child))
        }

        if (j.children && j.children.length > 0) {


             initializeComponent(j)

            console.log("Hi I am " + j["tagName"] + " and a parent")


            j.children.forEach((c) => {
                console.log("Hi I am " + c["tagName"] + " and my parent is " + j["tagName"])
                recursiveInitialize(c)
            });


        }

        else {
            console.log("Hi, I dont have any kids, I am " + j["tagName"])
            initializeComponent(j)
        }
    }
    

  function initializeComponent(jsonBlock){
        let tempComponent = {
        		name: jsonBlock["tagName"]+ uuid.toString(),
            methods: {
                greet() {
                    store.setMessageAction(this)
                }
              },
            data: function() {
                return {
                    tagName: jsonBlock["tagName"],
                    classes: jsonBlock["classes"],
                    attrs: jsonBlock["attrs"],
                    children: jsonBlock["children"],
                    textNode: jsonBlock["textNode"],
                    on: {click: this.greet},
                    ref: uuid,
                }
            },
            beforeCreate() {
                this.uuid = uuid.toString();
                uuid += 1; 
                
            
            },
            render: function(createElement) {
                  return createElement(this.tagName, {
                    class: this.classes,
                    on: {
                        click: this.greet
                    },
                    attrs: this.attrs,
                }, this.textNode);
            },
            mounted() {
                // example usage
                console.log('This ID:', this.uuid);
            },
        }
        Components.push(tempComponent);
        return tempComponent
    }
 
    const App = new Vue({
        el: '#app',

        data: {
            children: [
                Components
            ],
        },
        beforeCreate() {
            recurse();
            console.log("recurseRan")
        },

        mounted() {
            this.populate()
        },

        methods: {
            populate() {
                let i = 0;
                let numberOfItems = Components.length;

                for (i = 0; i < numberOfItems; i++) {
                    console.log("populate: " + Components[i])
                    this.children.push(Components[i]);
                }

            },
        }
    });
 
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>


                        <div id="app">
                            <template v-for="(child, index) in children">
                                <component :is="child" :key="child.name"></component>
                            </template>
                        </div> 

于 2020-05-24T20:19:13.377 回答