2017-05-30 87 views
2

我在.vue文件中有一個<filter>組件,它具有一些控制查詢過濾器的屬性。VueJS - 動態重複組件

這個<filter>可以根據用戶需要隨時添加/刪除。它的行爲與Google Analytics細分過濾器或WordPress的高級自定義字段非常相似。

我看到的唯一解決方案是動態實例化這個組件,並在我的主app中迭代這些組件的數組,但我並不完全知道該怎麼做。

Vue.component("my-filter", { 
 
    template: "#filterTemplate", 
 
    data: function() { 
 
    return { 
 
     field: null, 
 
     value: null 
 
    } 
 
    }, 
 
    mounted: function() { 
 
    this.$emit("filter-created", this); 
 
    }, 
 
    methods: { 
 
\t removeFilter: function() { 
 
\t  console.log("Remove this filter"); 
 
    } 
 
    } 
 
}); 
 

 
var app = new Vue({ 
 
    el: "#app", 
 
    data: { 
 
    filtersCount: 5, 
 
    filters: [] // PROBLEM! I can't decrement on my filtersCount and remove the correct filter. Iteration should be over my "filtersCount" property. 
 
    }, 
 
    methods: { 
 
    filterCreated: function(filterObj) { 
 
\t \t \t this.filters.push(filterObj); 
 
    }, 
 
    addFilter: function() { 
 
    \t this.filtersCount += 1; 
 
    } 
 
    } 
 
});
* { 
 
    font-family: "Helvetica", "mono"; 
 
    font-size: 16px; 
 
} 
 

 
.filterContainer + .filterContainer { 
 
    margin-top: 10px; 
 
} 
 

 
.filterContainer { 
 
    display: block; 
 
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.3.3/vue.min.js"></script> 
 
<div id="app"> 
 
<!-- I shouldn't iterate over an integer value, but over an array of objects to remove the right ones --> 
 
    <my-filter v-on:filter-created="filterCreated" v-for="(index, filter) in filtersCount" :key="index"></my-filter> 
 
    <br> 
 
    <button @click="addFilter">Add filter</button> 
 
</div> 
 
<script type="text/x-template" id="filterTemplate"> 
 
    <div class="filterContainer"> 
 
    <input type="text" :value="field" placeholder="Field" /> 
 
    <input type="text" :value="value" placeholder="Value" /> 
 
    <button @click="removeFilter">Remove filter</button> 
 
    </div> 
 
</script>

+1

你可以添加你所擁有的代碼,那麼遠? –

+0

你好亞當。我其實沒有任何與我的主應用程序相關的代碼。我只有我的組件的代碼,但我不相信它會對問題有用,對不起。如果你能給我一些關於如何去做的理論...... – juniorgarcia

+0

你可以把一些簡單的例子放在一起嗎? 「如果我有這些,我想補充一點,那麼我應該得到這樣的」那種東西? –

回答

0

有幾件事情是可以改變的,以得到它的工作(我只是假設你在找什麼!)

首先,你並不需要一個數據屬性用於計數過濾器(filtersCount),您可以循環使用filters屬性

其次,將this添加到filters屬性可能會導致意外的行爲,因爲this引用整個Vue組件。我建議添加代表filter數據的簡單對象並將數據作爲props傳遞。注意:該索引也作爲可以引用的道具傳遞,並允許通過發射刪除過濾器

最後,您的v-for似乎被顛倒過來。它應該是(filter, index)而不是(index, filter)

Vue.component("my-filter", { 
 
    template: "#filterTemplate", 
 
    props: [ 
 
    'field', 
 
    'value', // filter data 
 
    'id', 
 
    'index' // index that allows this filter to be removed 
 
    ], 
 
    data: function() { 
 
    return { 
 
     field: this.field, 
 
     value: this.value 
 
    } 
 
    }, 
 
    methods: { 
 
    removeFilter: function() { 
 
     this.$emit('remove-filter', this.index); 
 
    }, 
 
    handleInput: function(prop, e) { 
 
    \t this.$emit('update-filter', { index: this.index, prop, value: e.target.value }); 
 
    } 
 
    } 
 
}); 
 

 
window.vm = new Vue({ 
 
    el: "#app", 
 
    data: { 
 
    filters: [ 
 
     { id: 1, field: null, value: null }, 
 
     { id: 2, field: null, value: null }, 
 
     { id: 3, field: null, value: null }, 
 
     { id: 4, field: null, value: null }, 
 
     { id: 5, field: null, value: null } 
 
    ] 
 
    }, 
 
    methods: { 
 
    addFilter: function() { 
 
\t var id = Math.max.apply(Math,this.filters.map(function(o){return o.id;})) + 1; 
 
     this.filters.push({ id, field: null, value: null }); 
 
    }, 
 
    removeFilter: function(index) { 
 
     this.filters.splice(index, 1); 
 
    }, 
 
    updateFilter: function(payload) { 
 
     this.filters[payload.index][payload.prop] = payload.value; 
 
    } 
 
    } 
 
});
* { 
 
    font-family: "Helvetica", "mono"; 
 
    font-size: 16px; 
 
} 
 

 
.filterContainer + .filterContainer { 
 
    margin-top: 10px; 
 
} 
 

 
.filterContainer { 
 
    display: block; 
 
    border: 1px solid black; 
 
    padding: 5px; 
 
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.3.3/vue.min.js"></script> 
 
<div id="app"> 
 
    <button @click="addFilter">Add Filter</button> 
 
    <br><br> 
 
    <my-filter v-for="(filter, index) in filters" :key="index" :field="filter.field" :value="filter.value" :id="filter.id" :index="index" @remove-filter="removeFilter" @update-filter="updateFilter"></my-filter> 
 
</div> 
 

 
<script type="text/x-template" id="filterTemplate"> 
 
    <div class="filterContainer"> 
 
    \t <div>Index: {{ index }}, ID: {{ id }}</div> 
 
    <input type="text" :value="field" placeholder="Field" @input="handleInput('field', $event)" /> 
 
    <input type="text" :value="value" placeholder="Value" @input="handleInput('value', $event)" /> 
 
    <button @click="removeFilter">Remove filter</button> 
 
    </div> 
 
</script>

+0

你的例子似乎不工作。刪除任何過濾器將彈出數組數據,而不是刪除選定的索引。他們也沒有反應性。讓我們想象一個場景,我只需要從一個過濾字段開始。我將如何實例化此字段以使我的for循環工作? – juniorgarcia

+0

我用更多的視覺效果更新了我的示例。濾波器正在被正確刪除,但它保持清除濾波器值。我也爲輸入添加了反應性。至於從一個過濾字段開始,只需在filters數組中留下一個對象。 –

+1

完美的工作,儘管有點混亂,首先要了解兒童和父母的屬性所需的掛鉤。我剛剛意識到':key'不應該是循環的'index'值**,在我的情況下**,因爲當我在我的主數據上嘗試一個'splice'時它會改變。我在我的案例中所做的更改是將':key'的值設置爲'filter.id'。謝謝。 – juniorgarcia