как решить - Наличие дубликата слота "default" в том же дереве рендера - PullRequest
0 голосов
/ 08 мая 2018

Примечание. Поначалу может показаться, что вы ответили несколько раз, но я чувствую, что у меня другой случай.

При использовании <slot> несколько раз получаю ошибку ниже.

Наличие дубликата слота "default" в том же дереве рендеринга - это, вероятно, приведет к ошибкам рендеринга.

Есть решение использовать Scoped Slots, но я понимаю, чтоэто хорошо для использования с v-for.Я не уверен, возможно, я ошибаюсь, дайте мне знать, если я:)

У меня есть ситуация, когда мне нужно дублировать статический контент (с разметкой) в дочернем компоненте несколько раз.

// Parent Component
<template>
  <child-comp>
    <h1>Lorem Ipusm</h1>
    <button @click="fnDoSomething">Yahoo!<button>
    // ... there will be lot more lines of markups that will go here in default slot
  <child-comp>     
<template>


// Child Component
<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, тогда, пожалуйста, помогите мне и дайте мне знать, как клонировать слот (или что-то в этом роде), и он все еще будет реагировать.

1 Ответ

0 голосов
/ 08 мая 2018

Использование Функция рендеринга должна иметь возможность реализовать то, что вам нужно, как показано ниже:

Но вы можете столкнуться с некоторыми проблемами, такими как эта ссылка: Почему дублированные слоты плохи? .

Как сказал разработчик из основной команды Vue.js:

Vue будет повторно использовать те же объекты vnode (которые представляют элементы) несколько раз во время фактического создания элементов DOM.

Проблема в том, что каждый vnode получает ссылку на свой соответствующий набор элементов DOM.

Если вы повторно используете одни и те же объекты vnode несколько раз, эти ссылки перезаписать, и вы получите элементы DOM, которые не имеют представление в виртуальном домене, или vnodes, которые ссылаются на неправильные элемент.

Итак, в приведенной ниже демонстрации, когда вы нажмете кнопку, вы обнаружите, что первый слот первого случая не синхронизирован (VNode перезаписан).

Если ваш слот по умолчанию полностью статичен, то он не привязывается ни к каким свойствам и методам, поэтому следует использовать несколько слотов по умолчанию в render (). Но если нет, то для реализации того, что вам нужно, вы должны использовать ограниченный слот.

Или вы можете глубокий клон this.$slots.default (проверьте конструктор VNode ), это позволит избежать перезаписанной проблемы. (проверьте третий случай в демоверсии ниже)

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>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...