【问题标题】:How do I implement APIs in a search bar on VueJS?如何在 VueJS 的搜索栏中实现 API?
【发布时间】:2020-08-23 09:07:30
【问题描述】:

我正在从事一个大学项目,我一直在尝试实现一个搜索栏,该搜索栏从 API (https://api.rawg.io/api/games) 获取游戏名称,并在单击游戏后将用户重定向到特定页面游戏网址。现在,我希望我至少能够完成第一部分。

我创建了一个 searchbar.vue 组件并从官方 Vuetify 库中复制粘贴代码: (https://github.com/vuetifyjs/vuetify/blob/master/packages/docs/src/examples/autocompletes/simple/api.vue)

但是,如果我将 API 从他们作为示例提供的 API 更改为我需要的 API (rawg),它将不再起作用,我不知道为什么。

如何使我的搜索栏正常工作?

我提供了我目前正在工作的代码框的链接,以备不时之需: (https://codesandbox.io/s/searchbar-mtjr2?file=/src/components/searchbar.vue)

如果需要,我会尽力提供有关该问题的更多信息。

非常感谢您考虑这篇文章。

【问题讨论】:

  • Here's a working version of searchbar.vue. 搜索栏有效,但由于某种原因我无法弄清楚,搜索结果偏移到最右边,而不是停留在搜索栏下方。如果您根本看不到菜单,请查看codepen in the browser,打开检查菜单(F12)并将页面向左拖动,您应该会看到类似this的搜索结果。
  • 我能想到发生这种情况的唯一原因是您有一些其他样式干扰了搜索栏,但我查看了文件并找不到任何可能干扰搜索栏的样式搜索栏。如果您自己无法找到解决方案,您可能想提出一个单独的问题。
  • @MarsNebulaSoup 首先,非常感谢您的帮助。您的代码确实有效,这很棒。然而,现在我看它,它只返回了前 20 场比赛(RAWG API 的第一页)。我的问题是:我注意到 rawg API 中有一个名为“search”的开放 API 端点(api.rawg.io/docs/#tag/games)。你认为有可能以某种方式在搜索栏中使用它吗?不幸的是,我不太了解如何正确使用端点。至于“图形”错误,我会研究一下!再次感谢您的帮助。
  • 只要不是在每次击键时都执行搜索,search 参数对搜索游戏很有用。那很可能会很慢。如果您想要更多结果,您可以将?page_size=40 附加到API URL,使其看起来像https://api.rawg.io/api/games?page_size=40。当然,您可以将40 更改为您想要显示的结果数。请注意,如果页面中的游戏数量增加,请求大小会随着数量的增加而变大,因此数据加载速度会变慢。 40虽然不算多,但是如果你将大小设置为1000或其他东西,它可能会变慢。
  • 如果您想在 API URL 中添加任何参数,您所要做的就是在 url (?) 之后添加一个问号。然后添加param=value等参数。用 & 号分隔多个参数 (&)。像这样的东西:api.rawg.io/api/games?page_size=40&search=Grand theft auto

标签: vue.js vuetify.js searchbar


【解决方案1】:

相信搜索栏的所有问题都已经解决了:Demo here

我在代码中添加了 cmets,所以应该清楚它是如何工作的。

searchbar.vue:

<template>
  <v-autocomplete
    clearable
    :loading="isLoading"
    :items="games"
    :search-input.sync="search"
    hide-details
    item-text="name"
    item-value="id"
    label="Search for a Game..."
    solo-inverted
  ></v-autocomplete>
</template>

<script>
import _ from "lodash";

export default {
  data: () => ({
    games: [], // this is where all the game data will be stored
    isLoading: true, // variable to determine if the results are still being fetched from the API
    search: null // this is where the query will be stored
  }),
  methods: {
    getGames(params = "") {
      // this function will fetch game data from https://api.rawg.io/api/games with whatever api parameters you pass to the parameter `params`
      this.axios
        .get("https://api.rawg.io/api/games" + params)
        .then(resp => {
          // fetch data
          let tempGames = [...this.games.slice(0), ...resp.data.results]; //copy of this.games + new data
          this.games = _.uniqBy(tempGames, "id"); // remove any duplicates
          this.isLoading = false; // now that the data is in the array `games`, we can set isLoading to false
        })
        .catch(e => {
          // code to run if there was an error
          console.error(e); // display error message
        });
    },
    searchGames(query) {
      // this function will call getGames() with the search query formatted as an API parameter (?search=YOUR_QUERY)
      let searchQuery = encodeURI("?search=" + query); // URI encode the query so it is able to be fetched properly
      this.getGames(searchQuery);
    }
  },
  watch: {
    search: _.debounce(function(query) {
      // debounce with a a value of 250 will allow this function to be every 250 milliseconds at most. So if the user is typing continually, it won't run until the user stops.
      this.searchGames(query);
    }, 250)
  },
  created() {
    this.getGames(); // load the first 20 games initally
  }
};
</script>


这将:

  1. 加载前 20 个游戏
  2. 当您输入查询并停止输入时,它将向https://api.rawg.io/api/games?search=YOUR_QUERY 执行请求,并将结果添加到games 数组中。 (所以每次搜索,保存的游戏数组都会增加。这意味着如果您搜索相同的游戏两次,而它仍然会在线搜索https://api.rawg.io/api/games?search=YOUR_QUERY,那么该游戏将已经在游戏数组中第一次,所以它会立即加载。)
  3. v-autocomplete 过滤并显示结果。

此方法在更快的连接上效果更好,因为结果加载速度更快。因此,如果您的连接速度较慢,则加载结果可能需要一些时间。不幸的是,这是无法解决的(尽管您可以预先加载大量数据,但不能保证您加载的内容就是用户将搜索的内容)

通过将 App.vue 中的父 &lt;div&gt; 更改为 &lt;v-app&gt; 解决了导航栏的图形问题,如下所示:

之前:

<template>
  <div id="app">
    <nav-bar></nav-bar>
    ...
  </div>
</template>

之后:

<template>
  <v-app id="app">
    <nav-bar></nav-bar>
    ...
  </v-app>
</template>

我还添加了lodash 作为去抖动(等到用户停止输入)和删除重复项的依赖项。

这是我正在处理的codepen

如果您有任何其他问题,请告诉我。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-08-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多