我想创建一个自定义Vue指令来省略标记,但在指令为真时呈现标记的内容。
例如,如果我的vue实例的数据被定义为
data:{
omitIt: true
}
如果标记看起来像这样:
<div v-omit="omitIt" class="someClass">
Hello world!
</div>
当omitIt
设置为false时,我希望将以下内容渲染到dom中:
<div class="someClass">
Hello world!
</div>
但是当omitIt
为真时,我只想将以下内容渲染到dom中:
Hello world!
我最初尝试通过执行以下操作来解决此问题(诚然,这不是自定义vue指令):
<template v-if="!omitIt">
<div class="someClass">
</template>
Hello world!
<template v-if="!omitIt">
</div>
</template>
以上并不漂亮,但我想也许它会起作用。但是,当omitIt
为假时,会被渲染到dom中的是:
<div class="someClass"></div>
Hello world!
有关如何实现我正在寻找的结果的任何建议?
答案 0 :(得分:3)
这个答案错误,插槽不能以这种方式使用。请改为Bert's answer。
最简单的解决方案是为此目的创建一个包含slots的包装器组件,将省略的参数作为prop传递。
内容分发部分变得相当简单。
在包装器组件模板中:
<slot v-if="omitIt"></slot>
<div v-else>
<slot></slot>
</div>
您想要使用包装器的任何地方:
<wrapper v-bind:omitIt="omitIt">
// Content
</wrapper>
答案 1 :(得分:3)
我认为@Nit的答案是一个非常简单的答案并且支持它,但它确实有一个缺陷:插槽可能不是根元素,因此当需要省略包装时组件将失败。这是因为插槽可以包含多个元素,如果插槽 包含多个元素,则最终可能会有多个根元素,这是不允许的。
我有部分解决方案,如果组件不换行,则只会在插槽中呈现第一个元素。
Vue.component("wrapper", {
props:{
nowrap: {type: Boolean, default: false}
},
render(h){
// This will *only* render the *first* element contained in
// the default slot if `nowrap` is set. This is because a component
// *must* have a single root element
if (this.nowrap) return this.$slots.default[0]
// Otherwise, wrap the contents in a DIV and render the contents
return h('div', this.$slots.default)
}
})
这是一个工作的例子。
console.clear()
Vue.component("wrapper", {
props:{
nowrap: {type: Boolean, default: false}
},
render(h){
// Log a warning if content is being omitted
const omissionMessage = "Wrapper component contains more than one root node with nowrap specified. Only the first node will be rendered."
if (this.$slots.default.length > 1 && this.nowrap)
console.warn(omissionMessage)
// This will *only* render the *first* element contained in
// the default slot if `nowrap` is set. This is because a component
// *must* have a single root element
if (this.nowrap) return this.$slots.default[0]
// Otherwise, wrap the contents in a DIV and render the contents
return h('div', this.$slots.default)
}
})
new Vue({
el: "#app"
})
.someClass{
color: blue
}
<script src="https://unpkg.com/vue@2.4.2"></script>
<div id="app">
<wrapper class="someClass">Hello World</wrapper>
<wrapper nowrap>No wrap, single root</wrapper> <br>
<wrapper nowrap>
No wrap, two roots. Paragraph is ommitted.
<p>Some other content</p>
</wrapper>
</div>
一些注意事项:除非您将nowrap
添加为属性,否则组件将始终换行。另外,请注意,类被添加到包装容器中,而不将其指定为prop。这是因为Vue会自动渲染未在组件的根元素上指定为props的属性,除非您告诉它不要。