Vue 过滤器修改结果以限制返回的元素而不是添加它们

问题描述 投票:0回答:1

我有一个要过滤的元素的示例,如果过滤器被充分选择,则项目应该很少或没有,因为条件很难满足。在此处的源代码中,过滤器添加元素而不是限制它们出现在结果集中,如何更改条件或表达式来限制元素而不是添加


 get filteredProducts() {
      // products that have either a skill or usage value present within active filters
      if (!this.activeFilters.length) return this.products
      return this.products.filter(prod => (
        [prod.skill, prod.usage].some(val => this.activeFilters.includes(val))
      ))
    },
    activeFilters,
    products
  },

完整示例来自此处

<link href="//netdna.bootstrapcdn.com/bootstrap/3.0.0/css/bootstrap.min.css" rel="stylesheet" id="bootstrap-css">
<script src="//netdna.bootstrapcdn.com/bootstrap/3.0.0/js/bootstrap.min.js"></script>
<script src="//code.jquery.com/jquery-1.11.1.min.js"></script>
<!------ Include the above in your HEAD tag ---------->


<!DOCTYPE html><html lang='en' class=''>
<head><script src='//production-assets.codepen.io/assets/editor/live/console_runner-079c09a0e3b9ff743e39ee2d5637b9216b3545af0de366d4b9aad9dc87e26bfd.js'></script><script src='//production-assets.codepen.io/assets/editor/live/events_runner-73716630c22bbc8cff4bd0f07b135f00a0bdc5d14629260c3ec49e5606f98fdd.js'></script><script src='//production-assets.codepen.io/assets/editor/live/css_live_reload_init-2c0dc5167d60a5af3ee189d570b1835129687ea2a61bee3513dee3a50c115a77.js'></script><meta charset='UTF-8'><meta name="robots" content="noindex"><link rel="shortcut icon" type="image/x-icon" href="//production-assets.codepen.io/assets/favicon/favicon-8ea04875e70c4b0bb41da869e81236e54394d63638a1ef12fa558a4a835f1164.ico" /><link rel="mask-icon" type="" href="//production-assets.codepen.io/assets/favicon/logo-pin-f2d2b6d2c61838f7e76325261b7195c27224080bc099486ddd6dccb469b8e8e6.svg" color="#111" /><link rel="canonical" href="https://codepen.io/erikjung/pen/qmpjYm?depth=everything&order=popularity&page=83&q=vue&show_forks=false" />

<link rel='stylesheet prefetch' href='https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.0.0-alpha.6/css/bootstrap.min.css'>
<style class="cp-pen-styles">html,
body {
  min-height: 100%;
}

view-container {
  background: #eee;
  display: grid;
  grid-gap: 1px;
  grid-template-columns: minmax(20ch, 20vw) minmax(40ch, auto);
  grid-template-areas:
    "hd hd"
    "sd bd"
    "ft ft";
}

view-container > * {
  background: white;
  padding: 1rem;
}

view-head {
  grid-area: hd;
}

view-controls {
  grid-area: sd;
}

view-content {
  grid-area: bd;
}

view-foot {
  grid-area: ft;
}

img {
  max-width: 100%;
  opacity: .5;
}

button {
  cursor: pointer;
}

product-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(10ch, 20ch));
  grid-gap: 1rem;
}</style></head><body>
<view-container id="app">
  <view-head>
    <h3>Products</h3>
  </view-head>
  
  <view-controls>
    <div v-for="(filterset, key) in filters" style="min-width:20ch">
      <h6 v-text="`Filter by ${key}`"></h6>
      <ul class="list-unstyled">
        <li class="form-check" v-for="filter in filterset">
          <label class="form-check-label">
            <input class="form-check-input" 
                   type="checkbox" 
                   name="filters" 
                   v-bind:value="filter"
                   v-model="activeFilters">
            <span v-text="filter"></span>
          </label>
        </li>
      </ul>
    </div>
    <p v-if="activeFilters.length">
      <button class="btn btn-sm btn-secondary" 
              type="button"
              v-on:click="clearFilters">Clear Filters</button>
    </p>
  </view-controls>
  
  <view-content>
    <h6 v-text="`${filteredProducts.length} results`"></h6>
    <p v-if="activeFilters.length">
      <small class="text-muted" v-text="`Filtered by ${activeFilters.join(', ')}`"></small>
    </p>
    <product-grid>
      <div class="card" v-for="product in filteredProducts">
        <img class="card-img-top" src="http://fpoimg.com/300x200" alt="">
        <div class="card-block">
          <h5 class="card-title" v-text="product.name"></h5>
          <p class="card-text">
            <span v-text="`Price: $${product.price.toFixed(2)}`"></span>
            <br>
            <span v-text="`Skill: ${product.skill}`"></span>
            <br>
            <span v-text="`Usage: ${product.usage}`"></span>
          </p>
          <a class="btn btn-primary" href="#">Buy</a>
        </div>
      </div>
    </product-grid>
  </view-content>
  
  <view-foot>
    <p>
      <small class="text-muted" v-text="`${products.length} total / ${filteredProducts.length} shown`"></small>
    </p>
  </view-foot>
</view-container>
<script src='//production-assets.codepen.io/assets/common/stopExecutionOnTimeout-b2a7b3fe212eaa732349046d8416e00a9dec26eb7fd347590fbced3ab38af52e.js'></script><script src='https://cdnjs.cloudflare.com/ajax/libs/vue/2.2.4/vue.min.js'></script><script src='https://cdnjs.cloudflare.com/ajax/libs/ramda/0.23.0/ramda.min.js'></script>
<script >const products = [
  {name: 'Product 1', usage: 'Home', skill: 'Easy', price: 100.00},
  {name: 'Product 2', usage: 'Home', skill: 'Intermediate', price: 120.00},
  {name: 'Product 3', usage: 'Office', skill: 'Intermediate', price: 190.00},
  {name: 'Product 4', usage: 'Office', skill: 'Advanced', price: 260.00},
  {name: 'Product 5', usage: 'Warehouse', skill: 'Advanced', price: 320.00},
  {name: 'Product 6', usage: 'Farm', skill: 'Intermediate', price: 120.00},
  {name: 'Product 7', usage: 'Space', skill: 'Advanced', price: 157920.00},
  {name: 'Product 8', usage: 'Bathroom', skill: 'Easy', price: 9.00}
]

const tru = val => Boolean(val) === true

const hashValues = () => (
  location.hash.replace(/^#/, '').split(',').filter(tru)
)

const activeFilters = hashValues()

const vm = new Vue({
  el: '#app',
  data: {
    get uses() { 
      return R.pipe(R.pluck('usage'), R.uniq)(products)
    },
    get skills() { 
      return R.pipe(R.pluck('skill'), R.uniq)(products)
    },
    get filters() {
      return {
        'Usage': this.uses,
        'Skill': this.skills
      }
    },
    get filteredProducts() {
      // products that have either a skill or usage value present within active filters
      if (!this.activeFilters.length) return this.products
      return this.products.filter(prod => (
        [prod.skill, prod.usage].some(val => this.activeFilters.includes(val))
      ))
    },
    activeFilters,
    products
  },
  methods: {
    clearFilters() {
      this.activeFilters.splice(0, this.activeFilters.length)
    }
  },
  watch: {
    activeFilters: newVal => {
      location.hash = newVal.join(',')
    }
  }
})

window.onhashchange = () => {
  activeFilters.splice(0, activeFilters.length, ...hashValues())
}
//# sourceURL=pen.js
</script>
</body></html>

我希望在添加条件时从过滤器中返回更少的元素,并且使用 AND 而不是 OR

vue.js filter
1个回答
0
投票
[prod.skill, prod.usage].some(val => this.activeFilters.includes(val))

当产品技能或产品使用等于活动过滤器数组中找到的any值时,这行代码可以理解为返回true。

如果发现every活动过滤器包含在产品技能或产品使用中,您希望返回 true。

get filteredProducts() {
  // products that have both skill and usage value present within active filters
  if (!this.activeFilters.length) return this.products
  return this.products.filter(prod => (
    this.activeFilters.every(filter => [prod.skill, prod.usage].includes(filter))
  ))
},
© www.soinside.com 2019 - 2024. All rights reserved.