【问题标题】:Vue.js empty filter resultsVue.js 空过滤结果
【发布时间】:2015-09-23 15:23:46
【问题描述】:

在 Vue 中,我必须过滤一些数据:

<input v-model="search">
<ul>
    <li v-repeat="photo in photos | filterBy search in 'name'">
        <img src="{{ photo.src }}" alt="{{ photo.name }}">
    </li>
    <li v-if="!photos.length">
        No results, sorry!
    </li>
</ul>

如何检测空过滤结果并向用户显示适当的消息?

编辑

我目前正在执行以下操作,我觉得这是一个 hacky 解决方法:

HTML:

<input v-model="search">
<ul>
    <li v-repeat="photo in photos">
        <img src="{{ photo.src }}" alt="{{ photo.name }}">
    </li>
    <li v-if="!photos.length">
        No results, sorry!
    </li>
</ul>

Javascript:

var v = new Vue({
    data: {
        allPhotos: [...],
        photos: [],
        search: '',
    },
    ready: function () {
        var filter = Vue.filter('filterBy');
        var self = this;
        this.$watch('search', function () {
            self.photos = filter(self.allPhotos, self.search, 'name');
        }, {
            immediate: true
        });
    }
})

【问题讨论】:

    标签: vue.js


    【解决方案1】:

    Vue 2.x(更新)

    在 Vue 2.x 中,过滤器现在只能在文本插值内使用 as docs say

    Vue 2.x 过滤器只能在 mustache 绑定中使用。要在指令绑定中实现相同的行为,您应该改用计算属性。

    您可以使用 JavaScript 内置的 filter 方法和计算属性实现相同的行为。

    <input v-model="searchQuery">
    
    <span v-if="!filteredItems.length">No results.</span>
    
    <ul>
        <li v-for="item in filteredItems"></li>
    </ul>
    
    computed: {
      filteredItems: function () {
        var self = this;
        return self.items.filter(function (item) {
          return item.indexOf(self.searchQuery) !== -1;
        })
      }
    }
    

    Vue 1.x(原始答案)

    目前有两种方法。在所有情况下,模板看起来都一样。

    <input v-model="searchQuery">
    
    <span v-if="!filteredItems.length">No results.</span>
    
    <ul>
        <li v-for="item in filteredItems"></li>
    </ul>
    

    过滤依据

    通过$options访问的原始filterBy方法。

    computed: {
        filteredItems: function () {
            return this.$options.filters.filterBy(this.items, this.searchQuery);
        }
    }
    

    $评估

    更简洁的方法。评估表达式,就像您在模板中所做的那样。

    computed: {
      filteredItems: function () {
        return this.$eval('items | filterBy searchQuery');
      }
    }
    

    【讨论】:

    • Vue.js 最近有没有加入这个方法?我知道最近 Vue.js 发生了很多变化,而这个选项当时似乎不可用!我接受您的回答,因为它与“现在”更相关,干得好!
    • 您可以使用$eval 让它更干净一点,并像return this.$eval('items | searchQuery') 那样做,它还可以让您清楚地链接更多过滤器。
    • 很有可能。版本 >1.0 有很多变化。
    • 如何指定要过滤的项目属性?
    • 这个答案在 Vue 2.0 中不再有效。我相信 Dewey Waspada 下面的答案是最好的(也是唯一一个仍然适用于 2.0 的答案)。
    【解决方案2】:

    在 HTML 中:

    <input v-model="search">
    <h4 v-if="!filteredPhotos.length">No results</h4>
    <ul>
        <li v-for="photo in filteredPhotos">
            <img :src="photo.src" :alt="photo.name">
        </li>
    </ul>
    

    在 JS 中,你需要像这样使用计算属性:

    computed: {
      filteredPhotos: function () {
          return this.photos.filter(function(photo){
              return photo.name.indexOf(this.search) > -1;
          }.bind(this));
      }
    }
    

    演示:http://jsfiddle.net/crswll/Lr9r2kfv/37/

    【讨论】:

    • 谢谢,您拯救了这一天!顺便说一句,我确实使用v-attr 来设置动态属性,但我认为出于演示的目的,要关注我遇到的问题!
    • 一段时间后再次访问此问题。这绝对是正确的方法,尤其是在 Vue 2.0 出来之后。
    【解决方案3】:

    这只适用于 Vue 1.0,即使那样你也应该只使用计算属性。以防万一,我将把这个答案留在这里。


    您也可以使用 vm.$eval 和计算属性来执行此操作。

    computed: {
      filteredItems: function () {
        return this.$eval('items | filterBy searchQuery');
      }
    }
    

    并使用类似的东西

    <div v-if="filteredItems.length">
      <div v-for="item in filteredItems">
        {{ item.name }}
      </div>
    </div>
    <div v-else>
      No results found!
    </div>
    

    【讨论】:

      【解决方案4】:

      HTML/CSS 解决方案(以防万一,如果您在 2 年后仍试图修复它)

      /* all list items are visible */
      ul.that-list li { display: block; }
      
      /* ...exept last one*/
      ul.that-list li:last-child { display: none; }
      
      /* but if last one is also first one ... means the only one */
      ul.that-list li:first-child { display: block; }
      <h2>List with items</h2>
      <ul class="that-list">
        <!-- here is your v-for with any filters you want -->
        <li>1 - Item is here</li>
        <li>2 - Another One Here</li>
        <li>3 - And anothe one</li>
        <!-- this is your message -->
        <li>(!message) There is no items... sorry</li>
      </ul>
      
      <h2>Empty</h2>
      <ul class="that-list">
        <!-- v-for with no rendered items :c -->
        <li>(!message) There is no items... sorry</li>
      </ul>

      Also codepen link here

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-10-02
        • 1970-01-01
        • 2013-01-14
        • 2015-03-03
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多