Iam stugging on a problem to handle default slots with render() function.
I have two components, one that passes a string value innerHTML to my custom Component MySub. In MySub i wants to use the default slot to do further stuff with it.
My Parent:
import { defineComponent, h, VNode } from "vue";
import MySub from "./mySub.ts"
export default defineComponent({
render() {
return h(MySub, {}, 'innerHTML')
}
})
My Sub:
import { defineComponent, h, VNode } from "vue";
export default defineComponent({
data() {
return {
value: ''
}
},
mounted() {
if (this.$slots.default && this.$slots.default()[0]) this.value = <string>this.$slots.default()[0].children
},
render() {
return h('div', {}, [this.value ' "here my added Stuff"'])
}
})
Now to my problem: When i code it like this (above or link below), i get a warning calls: Non-function value encountered for default slot. Prefer function slots for better performance. I know whats todo to get rid of these message and why its exists. Just add a function call to the value in my MyParent return h(MySub, {}, () => 'innerHTML').
But when i do this, it get the following message: Slot "default" invoked outside of the render function: this will not track dependencies used in the slot. Invoke the slot function inside the render function instead. Also here, i know what the message wants to tell me, but i cant find a why to handle these problem.
I hope, i could explain my problem clear enough and somebody know what i can do.
Here is an Playground Example that reproduce exactly my problem.
CodePudding user response:
Dont know its the correct way to reply my own question, but i found and resolved the problem...
The problem isnt occur in the parent component. You always should call default slots within a function call like: () => 'innerHTML' for better performance (like the warn message is calling) cause to not render it, when its empty.
So i have to search for the problem in the child...
And the problem was the function mounted()
m̶o̶u̶n̶t̶e̶d̶(̶)̶ ̶{̶
i̶f̶ ̶(̶t̶h̶i̶s̶.̶$̶s̶l̶o̶t̶s̶.̶d̶e̶f̶a̶u̶l̶t̶ ̶&̶&̶ ̶t̶h̶i̶s̶.̶$̶s̶l̶o̶t̶s̶.̶d̶e̶f̶a̶u̶l̶t̶(̶)̶[̶0̶]̶)̶ ̶t̶h̶i̶s̶.̶v̶a̶l̶u̶e̶ ̶=̶ ̶t̶h̶i̶s̶.̶$̶s̶l̶o̶t̶s̶.̶d̶e̶f̶a̶u̶l̶t̶(̶)̶[̶0̶]̶.̶c̶h̶i̶l̶d̶r̶e̶n̶
}̶,̶
In the render() function, i used this.value that is declared outside in the data() and assigned in the mounted(). So i just had to put it inside like below:
getDefaultSlotValue() {
if (this.$slots.default && this.$slots.default()[0]) this.value = <string>this.$slots.default()[0].children
},
render() {
return h('div', {}, [this.getDefaultSlotValue() ' "here my added Stuff"'])
}
Iam not sure, but the problem seems to be no problem, when you call the MySub directly (to see in App.vue), cause the mounted() is normally called after rendering. But i dont know, whats vue exactly doing under the hood.
