javascript - 如何解决 - 在同一渲染树中发现重复存在插槽 "default"

标签 javascript vue.js vuejs2 vue-component

使用 <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/

相关文章:

javascript - PhantomJS 将字符变成坏数据

javascript - 需要帮助选择 JS/jQuery 事件

javascript - 当 [渲染 : "TypeError: Cannot read property ' length' of undefined"] is found in multiple files, 错误不只是一个时,背景可能是什么?

vue.js - 另一个组件内的组件不起作用 - webpack - Vue.js 2

javascript - 在 Vue 组件中将逻辑从指令转移到方法

javascript - 滚动后打开 javascript 窗口

javascript - 链接到 id(hash),检测哈希值,但 scrollTo 不会通过具有固定导航的 if 语句触发

javascript - Vue 组件 Vue-Instant

vue.js - "unsupported type error"带有用于 .HDR 文件类型的 RGBE 加载器

bower - 将 bower 组件添加到 vue webpack