【问题标题】:Render Functions and Recursive Components in VueVue 中的渲染函数和递归组件
【发布时间】:2020-09-11 11:22:28
【问题描述】:

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

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

我正在尝试遍历嵌套的 JSON,它本质上是在模仿 DOM。每个“节点”看起来像这样。您可以打开 fiddle 以查看更多嵌套的 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> 

【问题讨论】:

    标签: javascript vue.js recursion vue-component vue-render-function


    【解决方案1】:

    你有没有尝试过类似的事情

    // MyRecursiveComponent.vue
    <template>
      <div>
        <!-- node content -->
        <div v-for="childNode" in jsonData.children">
          <MyRecursiveComponent :jsonData="childNode" />
        </div>
      </div>
    <template
    

    【讨论】:

    • 那么我应该在哪里调用渲染函数来实际编译将替换它的 HTML?
    【解决方案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> 

    【讨论】:

    • 嗨,Maks,我认为您发布的代码与我的相同。
    猜你喜欢
    • 2021-03-10
    • 2019-12-10
    • 2019-12-21
    • 1970-01-01
    • 2018-06-14
    • 2018-05-04
    • 1970-01-01
    • 1970-01-01
    • 2019-10-20
    相关资源
    最近更新 更多