开发者问题收集

VueJs 不显示从 axios 承诺获取的图像,然后将图像 url 放在 src 中

2020-09-24
1394

我正在尝试调用一个 API,一旦我得到响应,我想定位 image_url 属性,但我收到此错误 渲染时出错:“TypeError:无法读取未定义的属性‘image_url’”无法读取 VueComponent.getImages1 (Info.vue?42ed:39) 上未定义的属性‘image_url’

我已经在另一个 Javascript 文件中测试了我的代码,在那里它可以运行,但由于某种原因,在这里却不行。我还检查了父状态是否通过 Vue 控制台正确地将数据发送到子状态,并且它已经起作用了。

Info.vue

<template>
  <section>
    <img :src="getImages1()" alt="./assets/notFound.png" />
    <img :src="getImages2()" alt="./assets/notFound.png" />
  </section>
</template>

<script>
import axios from "axios";

export default {
  props: {
    anime1: String,
    anime2: String,
  },

  methods: {
    animeFind(anime) {
      axios
        .get(`https://api.jikan.moe/v3/search/anime?q=${anime}`)
        .then(async function(response) {
          const id = await response.data["results"][0]["mal_id"];
          await axios
            .get(`https://api.jikan.moe/v3/anime/${id}`)
            .then(function(response) {
              return response.data;
            })
            .catch(function(error) {
              return error; // take care of this later
            });
        })
        .catch(function(error) {
          return error; // take care of this later
        });
    },
    // eslint-disable-next-line no-unused-vars
    getImages1() {
      let response = this.animeFind(this.anime1);
      return response["image_url"];
    },
    getImages2() {
      let response = this.animeFind(this.anime2);
      return response["image_url"];
    },
  },
};
</script>
<style></style>

我试过这样做并且它起作用了

main.js

const axios = require("axios");

const animeFind = (anime) =>
    axios
        .get(`https://api.jikan.moe/v3/search/anime?q=${anime}`)
        .then(async function (response) {
            const id = await response.data["results"][0]["mal_id"];
            await axios
                .get(`https://api.jikan.moe/v3/anime/${id}`)
                .then(function (response) {
                    console.log(response.data["image_url"]);
                })
                .catch(function (error) {
                    console.log(error);
                });
        })
        .catch(function (error) {
            console.log(error);
        });

animeFind("Naruto");
animeFind("Cowboy Bebop");

这是父组件,只有当单击按钮时,图像才会改变

<template>
  <section class="hero">
    <div class="parent-1">
      <h1 class="title is-1">Compare two animes! :)</h1>
    </div>

    <div class="columns">
      <div class="column">
        <b-field class="label" label="Anime 1">
          <b-input value="Enter the first anime!" v-model="anime1"></b-input>
        </b-field>
      </div>
      <div class="column">
        <b-field class="label" label="Anime 2">
          <b-input value="Enter the second anime!" v-model="anime2"></b-input>
        </b-field>
      </div>
    </div>
    <div class="button-spacing">
      <b-button class="button" type="is-primary" @click="checkComplete"
        >Compare!</b-button
      >
    </div>

    <Info :anime1="anime1" :anime2="anime2" v-if="success">Wow</Info>
  </section>
</template>

<script>
import Vue from "vue";
import Buefy from "buefy";
import "buefy/dist/buefy.css";
import Info from "./Info.vue";
Vue.use(Buefy);

export default {
  components: {
    Info,
  },
  data() {
    return {
      anime1: "",
      anime2: "",
      success: false,
    };
  },

  methods: {
    // log() {
    //   console.log(this.anime1);
    //   console.log(this.anime2);
    // },
    checkComplete() {
      if (this.anime1.length > 0 && this.anime2.length > 0) {
        // let animeData1 = this.animeFind(this.anime1);
        // let animeData2 = this.animeFind(this.anime2);
        this.success = true;
        return this.$buefy.toast.open({
          message: "Yay, just a moment now!",
          type: "is-success",
          position: "is-bottom",
          duration: 3000,
        });
      }
      this.success = false;
      return this.$buefy.toast.open({
        duration: 3000,
        message: `Please fill out both fields`,
        position: "is-bottom",
        type: "is-danger",
      });
    },
  },
};
</script>

2个回答

我认为你对承诺仍然有点困惑。你的 animFind 函数没有返回任何内容。

相反,尝试

<template>
  <section>
    <img :src="url1" alt="./assets/notFound.png" />
    <img :src="url2" alt="./assets/notFound.png" />
  </section>
</template>

<script>
import axios from "axios";

export default {
  props: {
    anime1: String,
    anime2: String,
  },
  data() {
    return {
      url1: '',
      url2: '',
      error: ''
    }
  },
  methods: {
    animeFind(anime, data) {
      axios
        .get(`https://api.jikan.moe/v3/search/anime?q=${anime}`)
        .then(response => {
          const id = response.data["results"][0]["mal_id"];
          axios
            .get(`https://api.jikan.moe/v3/anime/${id}`)
            .then(response => this[data] = response.data["image_url"]);
        })
        .catch(error => {
          this.error = error; // take care of this later
        });
    }
  },
  
  watch: {
    anime1: {
      immediate: true,
      handler(newVal, oldVal) {
        this.animeFind(newVal, 'url1');
      },
    },
    anime2: {
      immediate: true,
      handler(newVal, oldVal) {
        this.animeFind(newVal, 'url2');
      },
    },
  },
};
</script>

注意使用 if 箭头函数留在 vue 范围内

Sélim Achour
2020-09-24

getImages() 函数在 animeFind() 返回之前返回。因此 getImages() 将返回未定义。

您可以将 axios 调用放入钩子中,当您返回 response.data 对象时,您可以将其分配给数据对象中的属性。您使用此属性代替模板中的函数,因此组件将具有响应性。 请注意,您应该在 axios 调用中的外部函数上使用常规函数,并在 then() 响应上使用箭头函数来获取正确的 this

为简单起见,我只处理一个图像示例,但编辑它并不那么复杂。

<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<template>
  <section>
    <p>Show image here</p>
    <img :src="urlResponse['image_url']" alt="./assets/notFound.png">
  </section>
</template>

<script>
import axios from "axios";

export default {
  data() {
    return {
      urlResponse: {}
    };
  },

  props: {
    anime1: String,
    anime2: String
  },

  created() {
    this.animeFind(this.anime1);
  },

  updated() {
    this.animeFind(this.anime1);
  },

  methods: {
    animeFind: function(anime) {
      axios
        .get(`https://api.jikan.moe/v3/search/anime?q=${anime}`)
        .then(async response => {
          const id = await response.data["results"][0]["mal_id"];
          await axios
            .get(`https://api.jikan.moe/v3/anime/${id}`)
            .then(response => {
              this.urlResponse = Object.assign(
                {},
                this.urlResponse,
                response.data
              );
              return response.data;
            })
            .catch(function(error) {
              return error; // take care of this later
            });
        })
        .catch(function(error) {
          return error; // take care of this later
        });
    }
  }
};
</script>
<style></style>
piir
2020-09-24