2017-08-23 14 views
0

Vue.jsを使用してインタラクションを駆動するUIライブラリ用の選択されたドロップダウンリストと検索ボックスコンポーネントが実装されていますが、 Vue.jsが親と子のコンポーネント間の通信をどのように扱うように見えるかに問題があります。Vue.jsコンポーネントで定義されている子コンポーネントへのアクセスとフィルタリング<slot>

基本的に、私は達成することを目指しています、ライブラリのユーザはこのようなものを使用してHTMLに検索・選択の要素を定義することができるようにすることです:

<search-select> 
    <search-option value="foo">Foo</search-option> 
    <search-option value="bar">Bar</search-option> 
    <search-option value="baz">Baz</search-option> 
    <search-option value="foobar">Foobar</search-option> 
</search-select> 

search-select部品のための私のテンプレートは次のようになります。

<template> 
    <div class="search-select"> 
     <div class="placeholder" ref="placeholder"></div> 
     <ul class="dropdown"> 
      <input 
       type="text" 
       placeholder="Type to filter..." 
       v-on:input="updateFilter" 
      > 
      <slot></slot> 
     </ul> 
    </div> 
</template> 

アイデアはsearch-selectコンポーネントは、ユーザが選択できるオプションをフィルタリングするために入力する指定入力を、上記のテキスト入力ボックスを追加することです。完成したコンポーネントはthisのようになります。

しかし、私がドキュメントで知ることから、Vue.jsは、親の中から子コンポーネントのプロパティにアクセスする直接的な方法や、clickイベントなどを聞く方法も提供していません親の<slot>の子供から。

これは、ユーザーの入力に基づいて子供の可視性をフィルタリングする方法や、ユーザーが子どもの1つをクリックしたときにsearch-selectコンポーネントの値を更新する方法がないことを意味します。

Vue.js documentationには、子コンポーネントから親にイベントを渡す方法が記載されていますが、スロット内で定義された要素には適用できないように見えます。

コンポーネント間で情報を共有することに関するVue.jsのベストプラクティスに違反することなく、このユースケースに必要な親コンポーネントと子コンポーネント間の双方向通信の実装方法を教えてください。

答えて

1

event busを使用すると、この問題を解決できます。すべてのオプションを入力イベントを聴いたままにして、引き渡された引数に応じて自分自身を隠すかどうかを決めるようにしてください。
下記のfiddleまたはデモを参照してください。

const bus = new Vue(); 
 

 
Vue.component('search-option', { 
 
    template: ` 
 
    <option v-if="show" :value="this.$attrs.value"><slot></slot></option> 
 
    `, 
 
    created() { 
 
    bus.$on('filter', (input) => { 
 
     this.show = this.$attrs.value.includes(input); 
 
    }); 
 
    }, 
 
    beforeDestory() { 
 
    \t bus.$off('filter'); 
 
    }, 
 
    data() { 
 
    return { 
 
     show: true, 
 
    }; 
 
    }, 
 
}); 
 

 
Vue.component('search-select', { 
 
    template: ` 
 
<div class="search-select"> 
 
    <div class="placeholder" ref="placeholder"></div> 
 
    <ul class="dropdown"> 
 
     <input 
 
      type="text" 
 
      placeholder="Type to filter..." 
 
      v-on:input="updateFilter" 
 
      v-model="myinput" 
 
     > 
 
     <slot></slot> 
 
    </ul> 
 
</div> 
 
    `, 
 
    methods: { 
 
    updateFilter() { 
 
     console.log('update filter'); 
 
     bus.$emit('filter', this.myinput); 
 
    }, 
 
    }, 
 
    data() { 
 
    return { 
 
    \t myinput: undefined, 
 
    }; 
 
    }, 
 
}); 
 

 
Vue.component('parent', { 
 
    template: ` 
 
<div class="parent"> 
 
<search-select> 
 
    <search-option value="foo">Foo</search-option> 
 
    <search-option value="bar">Bar</search-option> 
 
    <search-option value="baz">Baz</search-option> 
 
    <search-option value="foobar">Foobar</search-option> 
 
</search-select> 
 
</div> 
 
    `, 
 
}); 
 

 
new Vue({ 
 
    el: '#app', 
 
})
<script src="https://unpkg.com/vue/dist/vue.min.js"></script> 
 
<div id="app"> 
 
    <parent></parent> 
 
</div>

+1

グレート、私のユースケースのために完璧に動作しますが、よろしくお願いします。 –

関連する問題