I’m new to the World of Vue.js and I have to build a recursive Component renderer that turns JSON into rendered Vue components.
So far the recursive rendering works just fine, except for the props I’m passing to the createElement function (code below 😉 ) is not available as props, but inside the $vnode.data object. Any ideas what I’m missing?
The mock JSON I’m using looks like this:
{ "_id": "aslwi2", "template": "NavigationBar", "data": {}, "substructure": [ { "_id": "assd2", "template": "NavigationBarListItem", "data": { "title": "NavList Item 1" } }, { "_id": "a2323uk", "template": "NavigationBarListItem", "data": { "title": "NavList Item 2" } } ] }
My Recursive Rendering Component:
const createComponent = function(node ,h){ if(!node || !node.template){ return; } let children = []; if(node.substructure instanceof Array){ node.substructure.map( async childNode => { const childComponent = createComponent(childNode, h); children.push(childComponent); }); } return h(node.template, {xdata : clone(node.data)}, children.length > 0 ? children : null ); }; export default Vue.component('Structure', { render: function(createElement){ if(!this.structure) return; const component = createComponent(this.structure, createElement, registry); console.log(component); return component; }, props: { structure: { type: Object } } })
And my dynamically instantiated components:
<!-- Component: NavBar --> <template> <div class="nav-bar"> <slot></slot> </div> </template> <script> export default { props: { data: { type: Object } } } </script> <!-- Component: NavBarListItem --> <template> <div class="nav-bar-item"> {{title}} </div> </template> <script> export default { data () { return { title : "default" } }, created() { console.log('list item: ', this) } } </script>
Inside the log of the created method in my list item component we find the passed props within the $vnode…
Advertisement
Answer
The problem is here:
return h(node.template, {xdata : clone(node.data)}, ...
I don’t know what xdata
is but it isn’t something you should be passing to h
. The options are documented at https://v2.vuejs.org/v2/guide/render-function.html#The-Data-Object-In-Depth.
To pass a props you’d use props
.
return h(node.template, {props : clone(node.data)}, ...
While I’m struggling a little to follow the intent behind your code it looks like you may also have a problem with NavBarListItem
not defining a title
prop. You can’t pass a title
unless it’s defined as a prop. Defining it in data
isn’t the same thing.