我有一个嵌套在多层组件中的组件。有作用域的插槽可以向下传递到此组件。我想检测出何时没有。
示例:
cbox.AutoCompleteMode = AutoCompleteMode.None;
在此示例中,作用域插槽从未从根组件传递到Vue.component("parent", {
template: `
<child>
<template slot="expand" slot-scope="{data}" v-if="$scopedSlots.expand">
<slot name="expand" :data="data"></slot>
</template>
</child>
`,
});
Vue.component("child", {
template: `
<div>
<slot name="expand" :data="1"></slot>
<div @click="$scopedSlots.expand && log()">Child</div>
</div>
`,
methods: {
log() {
console.log(this.$scopedSlots.expand);
console.log("This shouldn't work");
}
}
});
new Vue({
el: "#app",
template: `<parent></parent>`,
})
。结果,我会认为<parent>
中的$scopedSlots.expand
和v-if
都是虚假的,因此不会有任何槽位传递给<parent>
,并且单击不会做任何事情。
但是,这似乎是错误的,原因有两个:
<child>
是作为函数存储在内部的,因此它将始终评估为真实,如您在CodePen控制台中所见。$scopedSlots.expand
始终呈现,即使<template>
也是如此。因此,即使v-if="false"
在$scopedSlots.expand
中被评估为虚假,一个空位仍将传递给<parent>
,而<child>
内部的$scopedSlots.expand
将被评估为真实不管。有没有办法使这项工作成功?
我知道我可以通过传递一个布尔型道具来完成此操作,该道具指出是否要处理点击。我试图找出是否有可能从广告位本身确定。
答案 0 :(得分:3)
我以前曾被打过,这很烦人。
Vue模板编译器将对此进行编译
<template v-if="false"/>
本质上
vm._e()
其中_e
是createEmptyVNode
的{{3}}。因此,我们马上就会期望使用空vnodes 而不是虚假的值。
如果我们通过查看此模板的编译代码进行进一步调查
<child>
<template slot="expand" slot-scope="scope" v-if="false"/>
</child>
我们得到了这段代码(为了简化说明,只显示了相关内容)
_c('child', {
scopedSlots: {
expand(scope) {
return undefined
}
}
})
总结:v-if="false"
并非不是暗示将省略作用域插槽功能,而是提供范围的插槽功能,但调用时它将返回undefined
。因此,在子组件中,可以预期$scopedSlots.expand
存在,但是在调用时将返回undefined
。
AFAIK没有简单的方法来处理此问题。您的示例的快速“修复”将是
<div @click="$scopedSlots.expand() && log()">Child</div>
^^
但要警惕
slot-scope="{data}"
不存在的{data}
?最好使用真实的$scopedSlots.expand(scope)
数据调用scope
。$scopedSlots.expand()
并在渲染周期中多次丢弃潜在的真实结果可能是性能问题。 FWIW通过将v-if
和slot
分离到单独的<template>
节点中,成功实现了 variable :
<template v-if="$scopedSlots.expand">
<template slot="expand" slot-scope="{data}">
<slot name="expand" :data="data"/>
</template>
</template>