【问题标题】:Show loader on Vue 3 async axios request在 Vue 3 异步 axios 请求上显示加载器
【发布时间】:2022-01-13 21:01:12
【问题描述】:

这是我的第一个 Vue 3 项目...

我试图在 Axios 异步请求期间显示加载程序。 这是我的组件

<script setup>
  import { defineProps, onMounted, ref, computed } from 'vue';
  import axios from 'axios'
  const props = defineProps({
    publicKey: String
  })

  const tokens = ref([]);

  const loader = computed(() => {
    return tokens.value.length > 0
  })

  onMounted(async () => {
      console.log(loader);
      const url = `https://example.com/${props.publicKey}/nfts/metadata`
      const res = await axios.get(url);
      tokens.value = res.data;
      console.log(loader);
    });

</script>

<template>
  <div v-if="loader">
    <div class='anim-circle'></div>
  </div>

  <div v-else>
  {{tokens}}
  </div>
</template>

不行,我试了好几种方法都没有成功...

我就是这样编辑脚本的

<script setup>
import {
  defineProps,
  onMounted,
  reactive,
  computed
} from 'vue';
import axios from 'axios'
const props = defineProps({
  publicKey: String
})

let tokens = reactive([]);

const loaded = computed(() => {return !(tokens?.length > 0)})

onMounted(async () => {
  const url = `https://api.example.io/solana/account/${props.publicKey}/nfts/metadata`
  const res = await axios.get(url);
  tokens.push(...res.data);
});
</script>

<template>
<div v-if="loaded.value">
  <div class="row">

    <div v-for="token in tokens.nfts" v-bind:key="token.id" class="col-lg-4 col-md-6 col-12 mb-4 pb-2">
      <router-link :to="{ name: 'Token', params: { id: token.id }}">
      <div class="nft-collection nft-col-primary p-3 bg-white rounded-md">
        <img :src="token.image" class="img-fluid rounded-md shadow mb-2">

        <div class="content mt-3 p-2 rounded-md" style="background-color: white">
          <a class="title text-light h3" href="">
            {{token.name}}
            {{token.description}}
          </a>
          <ul class="pt-3 d-flex justify-content-between align-items-center list-unstyled mb-0">
            <li>
              <!-- <span v-for="skill in buddha.metadata" v-bind:key="skill" class="badge bg-soft">{{skill}}</span> -->
            </li>
          </ul>
        </div>
      </div>
      </router-link>
    </div>

  </div>
</div>
<div v-else>
  <div class="row loading">
  <div class='anim-circle'></div>
</div>
</div>
</template>

Token 现在是响应式的,我将 axios 调用的结果推送到数组中。 我更改为“已加载”,如果已加载则显示我的结果,如果未加载则显示加载器。

控制台的错误是

Uncaught (in promise) TypeError: Found non-callable @@iterator
    at eval (TokenList.vue?./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[0]!./node_modules/cache-loader/dist/cjs.js??ruleSet[0].use[0]!./node_modules/vue-loader/dist/index.js??ruleSet[0].use[1]:24)

另一次尝试性重构

<script setup>
import {
  defineProps,
  onMounted,
  ref,
  computed
} from 'vue';

import axios from 'axios'
const props = defineProps({
  publicKey: String
})

const tokens = ref([])
const loadingState = ref(null)
const showToken = computed(() => loadingState.value === 'success' )

// Fetch Data Feature
const fetchAllTokens = () => {
  console.log(showToken.value);
  loadingState.value = 'loading'
  const url = `https://api.unlocktech.io/solana/account/${props.publicKey}/nfts/metadata`
  return axios.get(url)
    .then(response => {
      loadingState.value = 'success'
      tokens.value = response.data.nfts
      console.log(tokens.value);
      console.log(showToken.value);
    })

}

onMounted(
  fetchAllTokens()
);
</script>

<template>
<div v-if="showToken.value">
  <div class="row">

    <div v-for="token in tokens.value" v-bind:key="token.id" class="col-lg-4 col-md-6 col-12 mb-4 pb-2">
      <router-link :to="{ name: 'Token', params: { id: token.id }}">
      <div class="nft-collection nft-col-primary p-3 bg-white rounded-md">
        <img :src="token.image" class="img-fluid rounded-md shadow mb-2">

        <div class="content mt-3 p-2 rounded-md" style="background-color: white">
          <a class="title text-light h3" href="">
            {{token.name}}
            {{token.description}}
          </a>
          <ul class="pt-3 d-flex justify-content-between align-items-center list-unstyled mb-0">
            <li>
              <!-- <span v-for="skill in buddha.metadata" v-bind:key="skill" class="badge bg-soft">{{skill}}</span> -->
            </li>
          </ul>
        </div>
      </div>
      </router-link>
    </div>

  </div>
</div>
<div v-else>
  <div class="row loading">
  <div class='anim-circle'></div>
</div>
</div>
</template>

在控制台中我有“false”,然后是“true”,但条件加载不起作用

【问题讨论】:

  • 究竟什么不起作用?什么是记录数据?有错误吗?
  • 我猜loader默认值设置为false。似乎tokens.value.lengthundefined,因此该语句将返回false。所以一开始不显示。您应该默认将其设置为true,并在响应到来时更改它。

标签: vue.js axios


【解决方案1】:

我认为对象(数组)应该是reactive 而不是ref

https://v3.vuejs.org/api/basic-reactivity.html

所以这是新代码:

<script setup>
  import { defineProps, onMounted, ref, computed } from 'vue';
  import axios from 'axios'
  const props = defineProps({
    publicKey: String
  })

  const tokens = reactive([]);

  const loader = computed(() => {
    return tokens?.length > 0
  })

  onMounted(async () => {
      console.log(loader);
      const url = `https://example.com/${props.publicKey}/nfts/metadata`
      const res = await axios.get(url);
      tokens = res.data;
      console.log(loader);
    });

</script>

<template>
  <div v-if="loader">
    <div class='anim-circle'></div>
  </div>

  <div v-else>
  {{tokens}}
  </div>
</template>

【讨论】:

    【解决方案2】:

    我认为“加载器”应该是

    const loader = computed(() =&gt; {return !(tokens?.length &gt; 0)})

    因为要显示加载器,如果令牌数组中没有项目。 此外,tokensconst,因此您无法重新分配它。你应该改用tokens.push(...res.data)

    此外,正如@ImagiNiha 所示,您应该使用reactive 而不是ref

    【讨论】:

    • 谢谢!我已经尝试过,但收到一个错误... :-( 使用 tokens.push(...res.data) 我无法列出我的令牌...
    • @Roberto Pezzali 你能提供你收到的错误吗?
    • 我编辑添加了根据您的建议重构的新代码。
    • 好的,我无法重现完全相同的错误,但我有一些建议。我认为错误是由此造成的。您尝试在v-for 中访问tokens.nfts。由于令牌是一个数组,它没有这个属性。那么 axios 请求是提供一组令牌还是只提供 1 个?如果只是 1 个对象,请尝试 'tokens.push(res.data)` 并调整 v-for 也不能使用 loaded.value,只需在模板中使用 loaded。其次,因为您切换了 v-if 订购正确的 loaded 现在是 const loaded = computed(() =&gt; {return tokens?.length &gt; 0))
    • 好的,我尝试推送数组而不是单个值。我也尝试了另一种方法,使用加载值更改为 axios 调用,但它不起作用
    猜你喜欢
    • 2020-03-16
    • 1970-01-01
    • 2018-08-27
    • 2017-01-26
    • 2018-11-18
    • 2018-06-01
    • 2019-04-12
    • 1970-01-01
    • 2018-02-17
    相关资源
    最近更新 更多