2

我有一个 Vuetify 自动完成功能,带有多个选择的芯片,其建议下拉菜单未存储在本地,但当用户开始在输入字段中输入时,总是从服务器异步检索。代码看起来像这样:

fetch("/echo/html/", {
    method: "POST",
    headers: {
      "Content-Type": "application/json; charset=utf-8"
    },
    body: "html=<a href='#'>hello world</a>"
  })
  .then((response) => response.rows = [{
      id: "6rfsda",
      name: "Cristiano Ronaldo",
      club: "Juventus FC"
    },
    {
      id: "vfgfas",
      name: "Lionel Messi",
      club: "FC Barcelona"
    },
    {
      id: "fgfaex",
      name: "Mohammd Salah",
      club: "Liverpool FC"
    }
  ])
  .catch((error) => {
    console.error(error)
  })

var vm = new Vue({
  el: "#app",
  data() {
    return {
      selectedFootballPlayers: [],
      footballPlayers: [],
      footballPlayerSearch: {
        loading: false,
        search: ''
      }
    }
  },
  watch: {
    'footballPlayer.search': function watch(val) {
      this.queryFootballPlayers(val);
    },
    selectedFootballPlayers() {
      this.footballPlayerSearch.search = '';
    },
  },
  methods: {
    async queryFootballPlayers(val) {
      this.footballPlayerSearch.loading = true;
      this.footballPlayers = [];
      if (this.selectedFootballPlayers.length > 0) {
        this.selectedFootballPlayers.forEach((player) => this.footballPlayers.push(player));
      }

      let response;

      try {
        const result = apiUrl.findFootballPlayers({
          query: val
        }); //I tried to get the async simulation call to work, but I have no clue how
        response = await result.response;
      } catch (err) {
        console.log('There was an error');
      }
      this.footballPlayerSearch.loading = false;
    },
    remove(item) {
      const itemIndex = this.selectedFootballPlayers.findIndex((el) => el.id === item.id);
      this.selectedFootballPlayers.splice(itemIndex, 1);
    },
  }
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<link href="https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/@mdi/font@5.x/css/materialdesignicons.min.css" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/vuetify@1.x/dist/vuetify.min.css" rel="stylesheet">
<link href='https://fonts.googleapis.com/css?family=Roboto:300,400,500,700|Material+Icons' rel="stylesheet" type="text/css">
<div id="app">
  <v-app light>
    <v-autocomplete v-model="selectedFootballPlayers" :items="footballPlayers" label="Favorite Footbal Players" :loading="footballPlayerSearch.loading" :no-data-text="'No football players were found'" :search-input.sync="footballPlayerSearch.search" item-text="name"
      return-object no-filter multiple style="width: 100%">
      <template v-slot:selection="data">
          <v-chip
            v-bind="data.attrs"
            :input-value="data.selected"
          >
          <span>{{ data.item.name }}</span>
            <v-icon
              right
              size="18"
              @click="remove(data.item)"
            >
              close
            </v-icon>
          </v-chip>
         </template>
      <template slot="item" slot-scope="{ item }">
           <v-list-tile-content>
             <div class="d-flex align-center justify-center">
               <v-checkbox
                 v-model="item.selected"
                 :ripple="false"
                 :label="item.name"
                 multiple
               />
               {{ item.name }}
             </div>
           </v-list-tile-content>
         </template>
    </v-autocomplete>
  </v-app>
</div>

(不幸的是,我无法让代码在 JSFiddle 中运行,因为我不知道如何在那里模拟异步调用。)

流程如下:

  1. 用户关注 v-autocomplete 字段。对前 20 名足球运动员进行第一次调用服务器。
  2. 用户开始键入字符串。使用字符串作为参数对服务器进行新调用,并返回新结果。
  3. 用户从结果中选择一些足球运动员。
  4. 用户键入一些新字符串,等等。

现在会发生什么?当用户键入新的搜索时,先前选择的筹码会立即消失。如果他从新的建议列表中选择一个筹码,则该筹码会显示在输入中,直到进行新的搜索,然后该筹码就会消失。这可以通过芯片不包含在建议中的事实来解释。我发现了一个关于它的技巧,即总是在建议中推送预先存在的选择,但这很丑陋,而且这不是用户所期望的。

我考虑改用组合框,但我不确定这是否能解决我的问题。

4

0 回答 0