如何在 Vue.js 插槽中使用条件渲染?
Posted
技术标签:
【中文标题】如何在 Vue.js 插槽中使用条件渲染?【英文标题】:How to use conditional rendering with Vue.js slots? 【发布时间】:2020-11-15 23:51:37 【问题描述】:如何使用 v-if
的结果在 Vue 中渲染两个不同的组件?如果重要的话,我也在尝试使用v-for
渲染TreeView
时这样做。这是我迄今为止尝试过的。
TreeView.vue:
<template>
<span>
<ul v-show="isOpen" v-if="isFolder">
<p
v-for="(child, index) in item.children"
v-bind:item="child"
v-bind:key="index"
<span v-if="!child.isFolder">
<slot v-bind:individualBookmark="child"></slot>
</span>
<span v-else>
<div v-bind:class="bold: isFolder" v-on:click="toggle" v-on:dblclick="makeFolder" v-on:contextmenu="rightClick">
child.name
<span v-if="isFolder">[ isOpen ? '-' : '+' ]</span>
</div>
</span>
</p>
</ul>
</span>
</template>
<script>
export default
name: "TreeView",
props:
item: Object
,
components:
,
data: function()
return
isOpen: false
,
computed:
isFolder: function()
return this.item.children.length > 0;
//return this.item.children && this.item.children.length;
,
methods:
toggle: function()
if (this.isFolder)
this.isOpen = !this.isOpen;
,
makeFolder: function()
if (!this.isFolder)
this.$emit("make-folder", this.item);
this.isOpen = true;
,
rightClick: function()
alert("Right click action")
</script>
App.vue
(Bookmark
标签是我构建的自定义组件,它不具有isFolder
计算属性):
<template>
<div id="app">
<TreeView v-slot:default="slotProps"
v-bind:item="treeData"
v-on:make-folder="makeFolder"
v-on:add-item="addItem">
<Bookmark v-bind="slotProps.individualBookmark"></Bookmark>
</TreeView>
</div>
</template>
<script>
import Bookmark from './components/Bookmark.vue'
import TreeView from './components/TreeView.vue'
import Vue from 'vue'
export default
name: 'App',
components:
Bookmark,
TreeView
,
data: function()
return
treeData :
name: "My Tree",
children: [
name: "hello" ,
name: "wat" ,
name: "child folder 1",
children: [
name: "child folder",
children: [ name: "hello" , name: "wat" ]
,
name: "hello" ,
name: "wat" ,
name: "child folder",
children: [ name: "hello" , name: "wat" ]
]
]
,
methods:
makeFolder: function(item)
Vue.set(item, "children", []);
this.addItem(item);
,
addItem: function(item)
item.children.push(
name: "new stuff"
);
</script>
当我运行它时,出于某种原因,TreeView.vue 中的 v-if="!child.isFolder"
总是评估为 true,因此它会呈现 Bookmark 组件。即使在v-if
应该评估为假的情况下,就像给定treeData
的“子文件夹1”子对象时一样,它仍然评估为真。我感觉问题与我在TreeView.vue
中使用<slot></slot>
的方式有关,但我不确定。为什么v-if
总是评估为真而不是假?
问题也可能与我编写isFolder
属性的方式有关。
【问题讨论】:
“你在 Treeview 组件中映射 item 属性并添加该属性”你能解释一下如何做到这一点吗?我不完全明白如何在代码中实现它 【参考方案1】:在 Treeview
组件内添加一个名为 computedChildren
的计算属性,该组件通过添加 isFolder
属性来映射 item 属性:
computed:
isFolder: function()
return this.item.children.length > 0;
//return this.item.children && this.item.children.length;
,
computedChildren()
return this.item.children.map(child=>
child.isFolder=child.children?child.children.length>0:false //this add the property isFolder
return child
)
,
然后循环如下:
<p
v-for="(child, index) in computedChildren"
...
要替换插槽,您可以使用 template
元素:
<TreeView
v-bind:item="treeData"
v-on:make-folder="makeFolder"
v-on:add-item="addItem">
<template v-slot:default="slotProps">
<Bookmark v-bind="slotProps.individualBookmark"></Bookmark>
</template>
</TreeView>
【讨论】:
谢谢,这最终将子文件夹呈现为文件夹。你知道我如何在子文件夹中呈现书签吗?子文件夹不显示它包含的书签。 不客气,请检查我编辑的答案,我使用模板元素呈现插槽内容 这似乎不起作用,这是我正在谈论的picture。子文件夹看起来已展开,但未显示其中包含的书签。此外,由于某种原因,当我单击子文件夹上的 [-] 按钮时,它会收回整个树,而它只应该收回子文件夹中的书签。 您能否提供一些codepen代码框示例以便对其进行调试 Here 是我的全部代码。再次感谢您的帮助。以上是关于如何在 Vue.js 插槽中使用条件渲染?的主要内容,如果未能解决你的问题,请参考以下文章