VueJS:过滤选择列表

时间:2020-06-10 08:07:54

标签: javascript vue.js

我有一个VueJS应用程序。我有两个列表:A,B

  • A包含所有元素
  • B包含A中的一些元素

我有<select>个标签。每个选择标签都必须包含B元素的值,并且应该可以选择B中不包含的其他A值。

问题:我如何正确过滤A中B中不存在的元素,但标签当时选择的元素除外?一种通用的解决方案是遍历每个元素,并从列表中取消设置不需要的元素。问题在于Vue具有反应性,这意味着当我更改自定义选择的列表时,更改也会传播到其他选择。

我已经包扎了一个多小时。我相信我正在为一个简单的问题构建场景,该问题具有简单的解决方案,但我找不到它。请帮助我。

const app = new Vue({
  el: '#app',
  data() {
    return {
      b: [],
      a: [
        1, 2, 3, 4, 5
      ],
    }
  },
  methods: {
    filterElements() {
      return this.a.filter((a, a_index) => {
        return !this.b.find((b, b_index) => {
          return a === b
        })
      })
    }
  }

})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>

<div id="app">
  <template v-for="i in b.length">
	<select v-model="b[i-1]">
	    <option value="0" disabled>Select a value</option>
	    <!--<option v-for="(item, index) in filterElements()" :value="item">{{ item }}</option> doesn't work -->
	    <option v-for="(item, index) in a" :value="item">{{ item }}</option>
	</select>
	<br>
			
  </template>
  <br>
  <button @click="b.push(0)">+</button>
  <br>
  <br>
  <div>Selected elements: {{ b.join(', ') }}</div>
</div>

3 个答案:

答案 0 :(得分:2)

您可以简单地使用计算属性来包含A的过滤版本

要跟踪B中的更改,您必须使用$set更新B中的元素。 否则,B不会反应。更多信息,https://vuejs.org/v2/guide/reactivity.html#For-Arrays

const app = new Vue({
  el: '#app',
  data() {
    return {
      b: [],
      a: [
        1, 2, 3, 4, 5
      ],
    }
  },
  computed: {
    filteredA() {
      return this.a.filter((a, a_index) => {
        return !this.b.find((b, b_index) => {
          return a === b
        })
      })
    }
  },
  methods: {
    updateB(e, i) {
      // use $set to update array elements to maintain reactivity
      this.$set(this.b, i, +e);
    }
   }
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>

<div id="app">
  <template v-for="i in b.length">
	<select :value="b[i-1]" @input="updateB($event.target.value, i-1)">
            <option :value="b[i-1]">{{b[i-1] || "Select a value"}}</option>
	    <!--<option v-for="(item, index) in filterElements()" :value="item">{{ item }}</option> doesn't work -->
	    <option v-for="(item, index) in filteredA" :value="item" :key="`${item}-${index}`">{{ item }}</option>
	</select>
	<br>
			
  </template>
  <br>
  <button @click="b.push(0)">+</button>
  <br>
  <br>
  <div>Selected elements: {{ b.join(', ') }}</div>
</div>

答案 1 :(得分:0)

无需手动过滤。这是一个循环a数组并将所选值绑定到b的解决方案:

https://stackoverflow.com/a/50648659/13602136

答案 2 :(得分:0)

如果我理解正确,则想进行数组减法(A中的元素不在B中):

function aNotInB(a, b) {
  return a.filter(aElement => {
    // .find() returns undefined if nothing is found
    // (b.find(element) === undefined) returns true if a element is not found in b
    return b.find(bElement => aElement === bElement) === undefined
  })
}

a = [1, 2, 3, 4, 5]
b = [2, 3, 4]


console.log(aNotInB(a,b))    // [1, 5]

相关问题