javascript - VueJS - 动态重复组件

标签 javascript vue.js repeater

我有一个 <filter> .vue 文件中的组件,它具有一些属性来控制查询的过滤器。

<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: {
	  removeFilter: function() {
	    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) {
			this.filters.push(filterObj);
    },
    addFilter: function() {
    	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>

最佳答案

可以更改一些内容以使其正常工作(我只是假设您正在寻找什么!)

首先,您不需要用于计算过滤器的数据属性 (filtersCount),您可以遍历 filters 属性(property)

其次,将this 添加到filters 属性可能会导致意外行为,因为this 引用了整个Vue 组件。我建议添加表示 filter 数据的普通对象并将数据作为 props 传递.注意:索引也作为一个 prop 传递,可以被引用并允许通过 emitting 移除过滤器

最后,您的 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) {
        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() {
      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">
    <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>

关于javascript - VueJS - 动态重复组件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44264907/

相关文章:

c# - 根据用户权限隐藏转发器列

qt - 使用中继器填​​充 GridLayout

javascript - 如何在 Angular 中用另一个对象过滤对象?

javascript - 如何限制用户访问 ExpressJS/NodeJS 中的静态 html 文件?

javascript - 在点击链接上发送 $_GET 变量 - PHP 和 Ajax

sorting - 排序()不工作

javascript - 在 Vue 项目中包含或初始化 jQuery 库的最佳方法是什么?

javascript - 如何让 CSS 类在我的 Javascript 文件中工作?

javascript - Vue.js:子组件如何改变父组件的状态?

c# - 嵌套中继器产生 "malformed server tag"?