如何解决vue api $slots.default 在使用 v-if 在插槽内渲染时不会再次评估
Vue slot 为开发者提供了极好的灵活性。
为了在slot内进行父子通信,使用eventbus是一个不错的方式。
但是我在父级中使用 $slots api 时遇到了一些问题。
当插槽内容由 $slots 指令呈现时,不会再次评估 v-if api。
例如,
Vue.component('parent',{
template:'<div v-if="visible"> <slot></slot></div>',data(){
return{
visible:false
}
},mounted(){
this.$on("triggerVisible",()=>{
this.visible = !this.visible;
//emit event to children in slot
this.emitEventtochildren();
})
},methods:{
emitEventtochildren(){
this.$nextTick(()=>{
this.$slots.default.forEach(item=>{
if(item.child)
item.child.$emit("eventFromParent",true);
})
})
}
}
});
Vue.component('child',{
template:'<div> <slot></slot></div>',data(){
return{};
},mounted(){
this.$on("eventFromParent",()=>{
this.$el.classList.add("event");
})
},});
var app = new Vue({
el:'#app',methods:{
triggerParent(){
this.$refs.parent.$emit("triggerVisible");
}
}
})
div.event{
background:#999;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<parent ref="parent">
<child>
<div >
Child1
</div>
</child>
<child>
<div >
Child2
</div>
</child>
<child>
<div>
Child3
</div>
</child>
</parent>
<button @click="triggerParent()">
Trigger
</button>
</div>
如您在示例中所见,第一次单击按钮时,它按预期工作。
css 样式类 event
被添加到每个元素。
但是当点击 trigger
按钮 2 次或更多次时,this.$slots.default
不会再次计算。
如果使用 v-show
而不是 v-if
,它可以正常工作。
请告诉我是什么原因。
解决方法
您应该避免使用 this.$el.classList
直接操作 DOM。看在上帝的份上,您正在使用 Vue!更改模板以根据组件状态动态呈现不同的 class
,并为事件使用全局事件总线或直接调用相应组件的方法(不是一个好的做法,但可以接受)。此外,不要忘记在卸载组件时取消订阅事件 - 否则您将在开发模式下使用热重新加载获得重复的处理程序:
Vue.component('parent',{
template:'<div v-if="visible"> <slot></slot></div>',data(){
return{
visible:false
}
},mounted(){
this.$root.$on("triggerVisible",()=>{
this.visible = !this.visible;
//emit event to children in slot
this.emitEventToChildren();
})
},beforeDestroy()
{
this.$root.$off('triggerVisible');
},methods:
{
emitEventToChildren()
{
this.$nextTick(()=>
{
this.$root.$emit('eventFromParent');
})
}
}
});
Vue.component('child',{
template:'<div :class="classList"> <slot></slot></div>',data(){
return {classList: ''};
},mounted(){
this.$root.$on("eventFromParent",()=>{
this.classList = "event";
})
},beforeDestroy()
{
this.$root.$off('eventFromParent');
}
});
var app = new Vue({
el:'#app',methods:{
triggerParent(){
this.$emit("triggerVisible");
}
}
})
div.event{
background:#999;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<parent ref="parent">
<child>
<div >
Child1
</div>
</child>
<child>
<div >
Child2
</div>
</child>
<child>
<div>
Child3
</div>
</child>
</parent>
<button @click="triggerParent()">
Trigger
</button>
</div>
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。