【问题标题】:How to create a search filter using Vue js from API Data?如何使用 API Data 中的 Vue js 创建搜索过滤器?
【发布时间】:2020-01-16 01:35:54
【问题描述】:

我正在从 Star Wars API 获取数据,更具体地说,是人员,它正在工作。我想创建一个搜索过滤器功能,当我开始输入时,只显示带有这些字母的名称。 这是我在 StarWarsPeopleComponent.vue 文件中获取数据的代码:

<template>
    <div class="container">
        <div class="row justify-content-center">
            <div class="col-md-8">
                <input type='text' v-model="search" placeholder='Search people...'/><br>

                {{ getAllStarWarsPeople() }}

                <ul>
                    <li v-for="person in people.results">
                        {{ person.name }}
                    </li>
                </ul>
            </div>
        </div>
    </div>
</template>

<script>

    export default {

        name: "StarWarsPeopleComponent",

        data() {
            return {
                people: [],
                search: ''
            }
        },

        mounted() {
            console.log('Component mounted.')
        },

        methods:{

            getAllStarWarsPeople() {

                fetch("https://swapi.co/api/people/")
                    .then(response=>response.json())
                    .then(data=>{
                        this.people=data;
                    })

            }

        }
    }
</script>

请注意我如何使用 people.results 访问 v-for 中的数据。

这是使用我创建的计算函数更新的组件,但现在数据未显示,我收到此错误:

[Vue warn]: Error in render: "TypeError: this.people.filter is not a function".

我对 Vue js 很陌生,我不知道这意味着什么或如何解决它。 有人可以帮忙吗?

<template>
    <div class="container">
        <div class="row justify-content-center">
            <div class="col-md-8">
                <input type='text' v-model="search" placeholder='Search people...'/><br>

                {{ getAllStarWarsPeople() }}

                <ul>
                    <li v-for="person in filteredPeople">
                        {{ person.name }}
                    </li>
                </ul>
            </div>
        </div>
    </div>
</template>

<script>

    export default {

        name: "StarWarsPeopleComponent",

        data() {
            return {
                people: [],
                search: ''
            }
        },
        mounted() {
            console.log('Component mounted.')
        },
        methods:{

            getAllStarWarsPeople() {

                fetch("https://swapi.co/api/people/")
                    .then(response=>response.json())
                    .then(data=>{
                        this.people=data;
                    })

            }

        },
        computed: {
            filteredPeople: function() {
                return this.people.filter((person) => {
                   return person.name.match(this.search);
                });
            }
        }
    }
</script>

【问题讨论】:

  • 在 vue 中,this 不能在外部函数中使用。改用 Evan 回答中的过滤器功能。
  • swapi 在这里并不是一个很好的选择,因为不可能通过关键字搜索。如果 swapi 实际上通过该请求返回所有人,那将不是问题,但它不是,它正在分页它,因此您需要发出后续请求以实际让所有人从中过滤,因为 people url 只是返回10 个人并为您提供 next 属性,例如:"next": "https://swapi.co/api/people/?page=2", 然后第 3 页等。考虑使用另一个免费 api,除非您想触发多个请求并将所有人存储在数组中以进行过滤:)

标签: javascript laravel api vue.js single-page-application


【解决方案1】:

在加载组件时使用“created()”调用getAllStarWarsPeople()。

在输入字段中将 getAllStarWarsPeople 添加为“@keyup”。

试试这个:

<template>
  <div class="container">
    <div class="row justify-content-center">
      <div class="col-md-8">
        <input
          type="text"
          v-model.trim="search"
          placeholder="Search people..."
          @keyup="getAllStarWarsPeople"
        /><br />
        <ul>
          <li v-for="person in people" :key="person.id">
            {{ person.name }}
          </li>
        </ul>
      </div>
    </div>
  </div>
</template>

<script>
export default {
  name: "StarWarsPeopleComponent",

  data() {
    return {
      people: [],
      search: ""
    };
  },

  mounted() {
    console.log("Component mounted.");
  },

  methods: {
    getAllStarWarsPeople() {
      fetch("https://swapi.dev/api/people/")
        .then(response => response.json())
        .then(res => {
          if (this.search) {
            this.people = res.results.filter(people =>
              people.name.toLowerCase().includes(this.search.toLowerCase())
            );
          } else {
            this.people = res.results;
          }
        });
    }
  },
  created() {
    this.getAllStarWarsPeople();
  }
};
</script>

这里是 JsFiddle:

new Vue({
  el: "#app",
  data: {
    people: [],
    search: ""
  },
  methods: {
    getAllStarWarsPeople() {
      fetch("https://swapi.dev/api/people/")
        .then(response => response.json())
        .then(res => {
          if (this.search) {
            this.people = res.results.filter(people =>
              people.name.toLowerCase().includes(this.search.toLowerCase())
            );
          } else {
            this.people = res.results;
          }
        });
    }
  },
  created() {
    this.getAllStarWarsPeople();
  }
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
  <div id="app">
    <input
      type="text"
      v-model.trim="search"
      placeholder="Search people..."
      @keyup="getAllStarWarsPeople"
    /><br />
    <ul>
      <li v-for="person in people" :key="person.id">
        {{ person.name }}
      </li>
    </ul>
</div>

【讨论】:

  • 是的,如果不想使用@keyUp handler,你也可以使用watch进行搜索。
  • 是的,我同意@KhairulHabib,我使用“@keyup”,对于初学者来说看起来更简单。
【解决方案2】:

你可以像这样使用

computed: {
  filteredPeople() {
    if (this.people) {
      return this.people.filter((person) => {
         return person.name.match(this.search);
      });
    }
    return false;
  }
}

【讨论】:

    猜你喜欢
    • 2021-07-29
    • 2018-06-22
    • 1970-01-01
    • 2021-11-08
    • 2019-01-10
    • 2019-03-03
    • 2020-10-07
    • 2021-12-18
    • 1970-01-01
    相关资源
    最近更新 更多