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.