使用template模式在属性传递时,若有h函数的执行,则可能会导致异常的报错
Vue version
3.3.0-beta.2
Link to minimal reproduction
Steps to reproduce
1、使用 template 标签
2、保证template生成sfc_render函数里有h函数的执行,比如:计算属性读取h函数执行的结果,一个方法的执行返回h函数执行的结果
3、使用v-show进行显示隐藏的切换时即会看到报错
What is expected?
预期是vnode生成正常,不报错
What is actually happening?
1、使用template模式在执行其生成的sfc_render函数时,会先通过openBlock方法分开层级关系 2、而openBlock之后,如果有某属性值的读取调用了h函数,也就会调用createVNode => createBaseVNode 3、createBaseVNode方法会往currentBlock里push对应创建的vnode 4、所以就会导致dynamicChildren的数量可能不一致(因为执行一次后结果会有缓存,但如果是计算属性数量也不一定不一致) 5、到后续patch时,就可能会有奇怪的结果,比如只更新了前面一部分,或者读取到节点的el不存在parentElement导致insertBefore error
System Info
No response
Any additional comments?
目前找到能用的一个方法是在使用h函数的前后,使用setBlockTracking来避免往currentBlock里push,但是不确定这是不是一个好办法
其它能想到的可能的处理方式是: 1、在h函数添加一个isBlockNode的参数,透传true来避免往currentBlock里push 2、或者使用setBlockTracking包一层h函数,类似slot那样,对外提供一个新方法?
duplicate of https://github.com/vuejs/core/issues/6913 as a workaround
const icon = computed(() => {
setBlockTracking(-1)
const res = h(BackTopIcon)
setBlockTracking(1)
return res
});
duplicate of #6913 as a workaround
const icon = computed(() => { setBlockTracking(-1) const res = h(BackTopIcon) setBlockTracking(1) return res });
好的,感谢确认!
这里为了保持向前兼容,setBlockTracking方法就必须保持public了,直到有新的api来处理这种情况
想问下这块有没有计划进行优化,以提供更简便的实现方式?
@nined9 see https://github.com/vuejs/core/pull/8213