BootstrapVue Popover 异常响应式行为问题排查
问题描述
我有一段类似如下的Vue模板代码:
<b-button id="button" @click="editingComment=true"> Click me </b-button> <b-popover target="button"> <template #title> <div>Comment is being<span v-if="editingComment"> {{ true ? 'edited' : 'created' }}</span></div> </template> <div id="content"> Content </div> </b-popover>
这段代码里的Popover标题能否正常响应状态更新,取决于一个看似无关的条件:我编写了脚本每2秒变更editingComment的状态——如果让另一个无关的Popover标题也依赖这个状态,两个Popover的标题都会随状态更新;但如果只有当前这个Popover依赖它,标题完全不会变化。这个问题是在迁移至Vue3兼容版后出现的,请问该行为的原因是什么?
原因分析
这是Vue3的响应式跟踪机制与BootstrapVue兼容版的Popover实现逻辑共同作用的结果:
- Vue3响应式依赖收集的时机特性:Vue3只会在组件模板渲染、读取响应式变量的阶段,为该变量建立跟踪关联。而BootstrapVue兼容版的Popover默认采用延迟渲染策略——标题模板只有在Popover第一次被触发显示时,才会真正执行渲染。
- 依赖收集错位导致的更新失效:
当只有单个Popover时,初始页面渲染阶段标题模板并未执行,editingComment没有被读取,Vue也就没有为这个Popover的标题建立响应式跟踪。后续editingComment状态变更时,Vue无法感知到需要更新该Popover的标题。
当存在另一个依赖editingComment的Popover时,那个Popover的标题在初始渲染时就读取了editingComment,成功建立跟踪。此时状态变更会触发该Popover的更新,而Vue的组件更新机制会连带触发同一父组件下的相关DOM更新,间接促使第一个Popover的标题被重新渲染,此时editingComment被读取,才补全了依赖跟踪,后续状态变更就能正常更新标题了。 - BootstrapVue兼容层的适配遗漏:Vue2中组件模板会被立即编译并完成依赖收集,但Vue3的兼容层没有妥善处理Popover这类延迟渲染组件的依赖收集逻辑,导致初始阶段依赖未被正确注册。
内容的提问来源于stack exchange,提问作者Oliver Coors
相关产品推荐
相关产品推荐

