【问题标题】:Filter an array based on user input in text box realtime根据文本框中的用户输入实时过滤数组
【发布时间】:2020-07-22 00:38:22
【问题描述】:

嘿,想要实时过滤在 vue js 中创建组件期间呈现的 JSON 对象数组

在挂载的生命周期钩子上有这个:

const search = document.querySelector('.search input');
    search.addEventListener('keyup',()=>{
      const term = search.value.trim();
         
         this.books = this.books.Title.filter(function (item) {
            return item.Title.match(term)   
})
      })

我尝试了几种不同的方法,但无法在数组上找到允许我动态过滤和更新数组的函数

任何能指引我正确方向的事情都会有所帮助!

搜索框:

  <form class="search">
      <input class="form-control m-auto" type="text" name="search" placeholder="search" />
   </form>

完整代码

template>
  <div>
    <div class="shelf" style="margin: 40px;">
      <h6>Here you can search a title of any book that is in the list</h6>
      <label for="fname">Search term:</label>
      <input type="text" id="fname" v-model="searchText">
      <ul class="collapsible popout">
        <h6 v-if="searchResults.length">Search results</h6>
        <li class="li" v-for="(book,index) in searchResults" :key="index">
          <div class="collapsible-header">
            <h5>
              {{ book.Title }}
            </h5>
          </div>
          <div class="collapsible-body">
            <p>Author: {{book.Author}}</p>
            <p>Category: {{book.Category}}</p>
            <div class="loan" v-if="book.Loan">on loan</div>
            <div class="owned" v-if="book.Owned">Owned</div>
            <!-- vue-router required to run this -->
            <!-- <router-link :to="{name:'EditBook', params:{id:book.id}}">
            <i class="material-icons">edit</i>
            </router-link>-->
          </div>
        </li>
      </ul>
    </div>
    <h5>Here is the list of avalaible books</h5>
    <ul class="collapsible popout" style="margin: 40px;">
      <li class="li" v-for="(book,index) in books" :key="index">
        <div class="collapsible-header">
          <h5>
            <book-icon/>
            {{ book.Title }}
          </h5>
        </div>
        <div class="collapsible-body">
          <p>Author: {{book.Author}}</p>
          <p>Category: {{book.Category}}</p>
          <div class="loan" v-if="book.Loan">on loan</div>
          <div class="owned" v-if="book.Owned">Owned</div>
        </div>
      </li>
    </ul>
  </div>
</template>
<script>
import db from '@/firebase/init'
import firebase from 'firebase'
import M from 'materialize-css'
export default {
  name: 'Shelf',
  data () {
    return {
      books:[],
      searchText: ''
    }
  },
  mounted(){
       var DropDownElems = document.querySelectorAll('.dropdown-trigger');
        let options = {
          inDuration: 300,
          outDuration: 300,
          hover: true, // Activate on hover
          coverTrigger: false, // Displays dropdown below the button
          };
        M.Dropdown.init(DropDownElems,options);
        var ColapseElems = document.querySelectorAll('.collapsible');
       M.Collapsible.init(ColapseElems)

    },
  created(){
      db.collection('Bookshelf').get()
      .then(snapshot=>{
        snapshot.forEach(book => {
          let b = book.data()
          b.id = book.id
          this.books.push(b)
             });
      })
    },
 computed: {
     searchResults() {
     if (this.searchText.length === 0) return "";
         return this.books.filter(book => book.Title.match(this.searchText));    
    }
  }
}
</script>
<style >
.loan{
    background: #ccc;
    box-shadow: 4px 3px 8px 1px #969696;
    -webkit-box-shadow: 4px 3px 8px 1px #969696;
    width: 150px;
    height: 150px;
}
.li{
  margin-left: 70px auto;
  margin-right: 70px auto;
 
}
.edit{
  left: 80%;
}
</style>

我能够验证 books 数组的输出一切正常

数组示例: 0: 作者:“串” 类别:“字符串” 贷款:布尔值 拥有:布尔值 现在阅读:布尔值 作品名称:《字符串》 id:“字符串”

从控制台:

当我运行返回 this.books.filter(book => console.log(book.Title));调试我得到一个字符串

【问题讨论】:

  • 什么是数据模型? this.books.Title.filter 看起来不对
  • 能否分享完整代码
  • 已编辑 - 主帖感谢@KarlL

标签: javascript vue.js


【解决方案1】:

您已经很接近了,但还需要一些改进。

首先,您不需要添加“标准”keyup 事件侦听器。使用 vue 你可以使用v-model:

在 Vue 应用程序中:

//...
name: 'Shelf',
  data () {
    return {
      books:[],
      term: ''
    }
  },
//...
<input type="text" v-model="term">

我建议您使用计算属性轻松获得过滤书:

computed: {
  filteredBooks() {
    const filteredBooks = this.books.filter(book => {  
        const regex = new RegExp(this.term.trim());
        return String(book.Title).match(regex)   
    });
  
    return filteredBooks;
  }
}

现在您可以遍历foundedBooks 以获取过滤后的图书:

<input type="text" v-model="term">

<div v-for="(book, index) in filteredBooks" :key="index">
  {{ index+1 }}. {{ book.Title }}
</div>

【讨论】:

  • 谢谢,但我不断收到“属性或方法“foundedBooks”未在实例上定义,但在渲染期间被引用”
  • 对不起,我打错了,应该是filteredBooks
  • 很抱歉在打错字后仍然这样做 - 我之前也发现了同样的结果
【解决方案2】:

欢迎使用 vue,让我举个例子,如何使用 Vue:

var app = new Vue({
  el: '#app',
  data: {
    // Our searchText property, used to filter the books
    searchText: '',
    // An array of books by Gabo
    books: [{
      title: "El coronel no tiene quien le escriba"
    },
    {
      title: "100 años de soledad"
    },
    {
      title: "Memorias de mis putas tristes"
    },
    {
      title: "El amor en los tiempos del cólera"
    }
    ]
  },
  computed: {
    // A computed property, magically listening changes
    // in the searchText property
    searchResults() {
      // If searchText property is empty, then return a empty string
      if (this.searchText.length === 0) return '';
      // return only books with titles that match with
      // the searchText string
      return this.books.filter(book => book.title.match(this.searchText))
    }
  }
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
  <label for="fname">Search term:</label>
  <input type="text" id="fname" v-model="searchText">
  {{ searchResults }} 
</div>

如果您对此有疑问或需要进一步解释,请告诉我

更多详情,请查看code

【讨论】:

  • 评论不适用于扩展讨论或调试会话;这个对话是moved to chat
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-09-21
  • 2011-04-13
  • 2018-08-14
  • 2019-10-12
相关资源
最近更新 更多