2017-02-22 5 views
1

Я пытаюсь создать список с расширяемыми элементами с помощью vue js 2. Идея в том, что когда я нажимаю на элемент, я хочу, чтобы он расширялся (показывал его содержимое) если он еще не расширен и не закрывает все остальные расширенные элементы. Я создал два компонента: expandable-panel и expandable-item. Я могу иметь несколько типов содержимого внутри, поэтому я хочу использовать слоты.Детский компонент испускает родительский и родительский обновления всех дочерних компонентов

код у меня есть:

ExpandablePanel компонент:

<template> 
    <div class="expandable-panel" @expanded="doStuff"> 
     <slot></slot> 
    </div> 
</template> 

<script type="text/babel"> 
    export default { 
     methods: { 
      doStuff: function() { 
       alert('expanded'); 
      } 
     } 
    } 
</script> 

ExpandableItem компонент:

<template> 
    <div class="expandable-item" @click="toggleExpand"> 
     <div class="expandable-item-header"> 
      {{ title }} 
     </div> 
     <div class="expandable-item-body" v-if="expanded"> 
      <slot></slot> 
     </div> 
    </div> 
</template> 
<script type="text/babel"> 
    export default { 
     props: { 
      title: String 
      // expanded: { 
      //  type: Boolean, 
      //  default: true 
      // } 
     }, 
     data: function() { 
      return { 
       expanded: true 
      } 
     }, 
     methods: { 
      toggleExpand: function() { 
       this.expanded = !this.expanded; 
       this.$emit('expand'); 
      } 
     } 
    } 
</script> 

И мой HTML файл

<expandable-panel> 
    <expandable-item title='title 1'>Lorem ipsum...</expandable-item> 
    <expandable-item title='title 2'>Lorem ipsum...</expandable-item> 
    <expandable-item title='title 3'>Lorem ipsum...</expandable-item> 
</expandable-panel> 

Моего приложения и компоненты зарегистрированы как это:

Vue.component('expandable-panel', require('./components/global/ExpandablePanel.vue')); 
Vue.component('expandable-item', require('./components/global/ExpandableItem.vue')); 
const app = new Vue({ 
    el: '#app' 
}); 

Проблема: $emit часть не кажется, доходит до @expanded="doStuff" внутри родительского компонента. Даже если он достигает, как правильно переключить значения expanded? Могу ли я использовать реквизиты для этого?

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

+1

Да, вы можете управлять им через реквизиты или также исследовать некоторые государственные управления, такие как [vuex] (https://vuex.vuejs.org/en/) для этой цели. – Saurabh

ответ

1

Вы здесь строгую связь между родителем и ребенком, так что вы можете излучать событие через объект $ parent.

Во-первых, на создание объекта родительским, слушать ваше мероприятие с this.$on:

Vue.component('parent', { 
    template: `<div><slot></slot></div>`, 
    created: function() { 
    this.$on('event', function(message) { 
     alert(message); 
    }) 
    } 
}); 

Затем внутри вашего ребенка компонента испускают это событие с $parent.$emit

Vue.component('child', { 
    template: `<button @click="$parent.$emit('event', 'From child')">I'm slot</button>` 
}); 

Здесь работает демо: https://jsfiddle.net/rdjjpc7a/1754/

+0

спасибо. Он работает так. –

0

В ExpandablePanel компонента: вы должны иметь только @expand, как это то, что вы испуская от ребенка:

<template> 
    <div class="expandable-panel" @expand="doStuff"> 
     <slot></slot> 
    </div> 
</template> 
+0

Спасибо за ваш ответ. У меня есть один вопрос. Где я должен определить метод 'doStuff', если он не должен находиться внутри' ExpandablePanel'? –

+0

@NightFall Это зависит от того, как вы хотите структурировать свое приложение. Должен ли родитель знать, расширен ли ребенок или нет? – Saurabh