使用 <slot>
时出现以下错误多次:
Duplicate presence of slot "default" found in the same render tree - this will likely cause render errors.
有一些使用“作用域插槽”的解决方案,但我的理解是,最好使用 v-for
的解决方案。 。我不确定,我可能是错的,如果我错了请告诉我。
我遇到了一种情况,需要在子组件中多次复制静态内容(带有标记)。
父组件:
<template>
<child-comp>
<h1>Lorem Ipusm</h1>
<button @click="fnDoSomething">Yahoo!<button>
<!-- ... there will be a lot more that will go here in the default slot -->
<child-comp>
<template>
子组件:
<template>
<div>
<h2>Need one default slot here</h2>
<slot><slot>
<div>
<h2>Need one more default slot here</h2>
<slot><slot>
<div>
</div>
<template>
如果上述问题无法解决或者是 Vue.js 的限制,那么请让我知道如何克隆插槽(或类似的东西)并使其仍然具有反应性。
最佳答案
使用render function应该能够实现您需要的内容,如下所示:
但是您可能会遇到一些麻烦,如此链接所述:Why are duplicated slots bad? .
正如 Vue.js 核心团队的开发者所说:
Vue would re-use the same vnode objects (which represent elements) multiple times during the actual creation of the DOM elements.
The problem with that is that each vnode gets a reference to its corresponding DOM element set.
If you re-use the same vnode objects multiple times, these references get overwritten and you end up with DOM elements that have no representation in the virtual dom, or vnodes that refer to the wrong element.
所以在下面的演示中,当您单击按钮时,您会发现第一个案例的第一个槽没有同步(VNode 被覆盖)。
如果您的默认插槽是完全静态内容,则不绑定(bind)到任何属性和方法,则在 render() 中使用多个默认插槽应该没问题。但如果没有,您必须使用作用域插槽来实现您需要的功能。
或者您可以深度克隆 this.$slots.default
(检查 VNode constructor ),它将避免覆盖问题。 (查看下面演示中的第三种情况)
Vue.config.productionTip = false
Vue.component('child', {
render: function (createElement) {
return createElement(
'div',
[
this.$slots.default, // default slot
createElement('div', {
attrs: {
name: 'test'
},
style: {fontSize: '10px', 'color':'green'}
}, this.$slots.default) // default slot
]
)
}
})
function deepClone(vnodes, createElement){
let clonedProperties = ['text','isComment','componentOptions','elm','context','ns','isStatic','key']
function cloneVNode(vnode) {
let clonedChildren = vnode.children && vnode.children.map(cloneVNode)
let cloned = createElement(vnode.tag, vnode.data, clonedChildren)
clonedProperties.forEach(function(item){
cloned[item] = vnode[item]
})
return cloned
}
return vnodes.map( cloneVNode )
}
Vue.component('child2', {
render: function (createElement) {
return createElement(
'div',
[
this.$slots.default, // default slot
createElement('div', {
attrs: {
name: 'test'
},
style: {fontSize: '10px', 'color':'green'}
}, deepClone(this.$slots.default, createElement) ) // default slot
]
)
}
})
Vue.component('child1', {
render: function (createElement) {
return createElement(
'div',
[
this.$slots.default, // default slot
createElement('div', {
attrs: {
name: 'test'
},
style: {fontSize: '10px', 'color':'green'}
}, this.$slots.my) // default slot
]
)
}
})
new Vue({
el: '#app',
data() {
return {
test: {
'item': 'test',
'prop1': 'a'
}
}
},
methods:{
changeData: function() {
this.test.item='none'
}
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.16/vue.js"></script>
<div id="app">
<button @click="changeData()">Click me!!!</button>
<h1 style="background-color:red">Use multiple default slot:</h1>
<child><h1>{{test}}</h1></child>
<h1 style="background-color:red">Use scoped slot instead:</h1>
<child1><h1>{{test}}</h1><template slot="my"><h1>{{test}}</h1></template></child1>
<h1 style="background-color:red">Use Deep Clone (Default) instead:</h1>
<child2><h1>{{test}}</h1><template slot="my"><h1>{{test}}</h1></template></child2>
</div>
关于javascript - 如何解决 - 在同一渲染树中发现重复存在插槽 "default",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50237182/