如何在 Vue 3 Composition 中使用 Axios API

How to use Axios with Vue 3 Composition API

我正在尝试根据以下教程使用 Vue 3 和 Composition API 构建一个 Pokemon 过滤搜索应用程序:https://www.youtube.com/watch?v=QJhqr7jqxVo. (GitHub: https://github.com/ErikCH/PokemonVue)

搜索组件中使用的 fetch 方法包括一个 reduce() 函数,用于根据 API 响应中分配给每个 Pokemon 的特定 ID 处理 urlIdLookup:

    const state = reactive({
      pokemons: [],
      filteredPokemon: computed(()=> updatePokemon()), 
      text: "",
      urlIdLookup: {}
      
    });

    fetch("https://pokeapi.co/api/v2/pokemon?offset=0")
      .then((res) => res.json())
      .then((data) => {
        console.log(data);
        state.pokemons = data.results;
        state.urlIdLookup = data.results.reduce((acc, cur, idx)=> 
           acc = {...acc, [cur.name]:idx+1 }
        ,{})
        console.log('url',state.urlIdLookup+1)
        
      });

urlIdLookup 然后被传递到用于显示所选口袋妖怪信息的路由:

    <div
      class="ml-4 text-2xl text-blue-400"
      v-for="(pokemon, idx) in filteredPokemon"
      :key="idx"
    >
      <router-link :to="`/about/${urlIdLookup[pokemon.name]}`">
        {{ pokemon.name }}
      </router-link>
    </div>

我不想使用上面的获取设置,而是希望使用 Axios 来处理来自 Pokemon 的请求和响应 API。在项目中安装axios并导入组件后,我新增了一个fetchPokemon方法:

    const fetchPokemon = () => {
      axios.get('https://pokeapi.co/api/v2/pokemon?offset=0')
      .then(response => {
        state.pokemons = response.data
      })
    }

    onMounted(() => {
      fetchPokemon()
    })

在这个新的获取方法中使用 Axios 时,我想像以前的获取设置一样处理 urlIdLookup,但如果可能的话,不使用 reduce() 方法和解结构累加器。我怎样才能使用 Axios 检索每个口袋妖怪的 urlId,然后将该 urlId 传递到模板中的“关于”路由?

这是完整的组件:

<template>
<div class="w-full flex justify-center">
<input placeholder="Enter Pokemon here" type="text" 
    class="mt-10 p-2 border-blue-500 border-2" v-model="text" />

</div>

  <div class="mt-10 p-4 flex flex-wrap justify-center">

    
    <div
      class="ml-4 text-2xl text-blue-400"
      v-for="(pokemon, idx) in filteredPokemon"
      :key="idx"
    >
      <router-link :to="`/about/${urlIdLookup[pokemon.name]}`">
        {{ pokemon.name }}
      </router-link>
    </div>
  </div>
</template>

<script>
import axios from 'axios';
import { reactive, toRefs, computed, onMounted } from "vue";
export default {
  setup() {
    const state = reactive({
      pokemons: [],
      filteredPokemon: computed(()=> updatePokemon()), 
      text: "",
      urlIdLookup: {}
      
    });

    const fetchPokemon = () => {
      axios.get('https://pokeapi.co/api/v2/pokemon?offset=0')
      .then(response => {
        state.pokemons = response.data
      })
    }

    onMounted(() => {
      fetchPokemon()
    })

    // fetch("https://pokeapi.co/api/v2/pokemon?offset=0")
    //   .then((res) => res.json())
    //   .then((data) => {
    //     console.log(data);
    //     state.pokemons = data.results;
    //     state.urlIdLookup = data.results.reduce((acc, cur, idx)=> 
    //        acc = {...acc, [cur.name]:idx+1 }
    //     ,{})
    //     console.log('url',state.urlIdLookup+1)
        
    //   });

    function updatePokemon(){
      if(!state.text){
        return [] 
      }
      return state.pokemons.filter((pokemon)=> 
          pokemon.name.includes(state.text)
      )
    }

    return { ...toRefs(state), fetchPokemon, updatePokemon };
  }
};
</script>

id好像没必要,为什么不用name作为id。如果你想使用整数 必须的,你可以foreach结果集索引是每个项目的id,然后

 <router-link :to="`/about/${pokemon.id}`">
        {{ pokemon.name }}
      </router-link>

如果我理解正确,请查看以下代码段:

const { reactive, toRefs, computed, onMounted } = Vue
const { axioss } = axios
const app = Vue.createApp({
  setup() {
    const state = reactive({
      pokemons: [],
      filteredPokemon: computed(() => updatePokemon()),
      text: "",
      urlIdLookup: {},
    });

    const fetchPokemon = () => {
      axios
        .get("https://pokeapi.co/api/v2/pokemon?offset=0")
        .then((response) => {
          state.pokemons = response.data.results; //  get just results
        });
    };

    fetchPokemon();
  
    //  function to get index
    const getPokemonId = (item) => {
      return state.pokemons.findIndex((p) => p.name === item);
    };

    function updatePokemon() {
      if (!state.text) {
        return [];
      }
      return state.pokemons.filter((pokemon) =>
        pokemon.name.includes(state.text)
      );
    }
                                                        //  return new function
    return { ...toRefs(state), fetchPokemon, updatePokemon, getPokemonId };
  },
})
app.mount('#demo')
<script src="https://unpkg.com/vue@3.2.29/dist/vue.global.prod.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/axios/0.26.1/axios.min.js" integrity="sha512-bPh3uwgU5qEMipS/VOmRqynnMXGGSRv+72H/N260MQeXZIK4PG48401Bsby9Nq5P5fz7hy5UGNmC/W1Z51h2GQ==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<div id="demo">
  <div class="w-full flex justify-center">
    <input
      placeholder="Enter Pokemon here"
      type="text"
      class="mt-10 p-2 border-blue-500 border-2"
      v-model="text"
    />
  </div>
  <div class="mt-10 p-4 flex flex-wrap justify-center">
    <div
      class="ml-4 text-2xl text-blue-400"
      v-for="(pokemon, i) in filteredPokemon"
      :key="i"
    >
                          <!-- //  call function to get index -->
      <router-link :to="`/about/${getPokemonId(pokemon.name)}`">
        {{ pokemon.name }} - id {{ getPokemonId(pokemon.name) }}
      </router-link>
    </div>
  </div>
</div>