正在摸鱼中,领导突然来个问题:为啥通过defineComponent封装的组件获取不到子组件的方法呢?正在学习vue3知识的我大为感兴趣,就研究了一下。
1、定义
2、使用
选项语法
const Comp = defineComponent({
setup(props) {
// 就像在 <script setup> 中一样使用组合式 API
const divEl = ref()
onMounted(() => {
console.log('7777', divEl.value)
})
return {
divEl
}
},
render() {
return h('div', [
h('div', {
innerHTML: 'word1',
onClick: () => {
console.log('render>>>>>', this.divEl)
}
}),
h(ElTree, { ref: 'divEl' })
])
}
})
函数语法
const Comp = defineComponent(
(props, { expose }) => {
// 就像在 <script setup> 中一样使用组合式 API
const divEl = ref()
onMounted(() => {
console.log('7777', divEl.value)
})
return () =>
h('div', [
h('div', {
innerHTML: 'word1',
onClick: () => {
console.log(divEl)
}
}),
h(ElTree, { ref: divEl })
])
},
// 其他选项,例如声明 props 和 emits。
{
props: {
/* ... */
}
}
)
3、问题
使用选项语法时,可以在父组件正常获取ElTree的方法。但是使用函数语法时获取的却是dom元素
查看defineComponent发现两者没有什么区别,函数语法判断第一个参数是否是函数,如果是函数,则将setup属性继承到组件配置中。最终返回的参数是一样的。
function defineComponent(options, extraOptions) {
return shared.isFunction(options) ? (
(() =>
shared.extend({ name: options.name },
extraOptions,
{ setup: options })
)()
) : options;
}
4、解决
直到在官方文档中看到setup与渲染函数一起使用的案例
这个就和上面的函数语法一样,setup返回的是一个渲染函数。而这样会造成一定的问题。
最终官方提供expose()解决问题
const Comp = defineComponent(
(props, { expose }) => {
// 就像在 <script setup> 中一样使用组合式 API
const divEl = ref()
onMounted(() => {
console.log('7777', divEl.value)
})
expose({
divEl
})
return () =>
h('div', [
h('div', {
innerHTML: 'word1',
onClick: () => {
console.log(divEl)
}
}),
h(ElTree, { ref: divEl })
])
},
// 其他选项,例如声明 props 和 emits。
{
props: {
/* ... */
}
}
)
可以关注我的公众号,交流相关技术,谢谢支持!