簡體   English   中英

如何讓子組件可以訪問 VueJs 中的父組件方法

[英]How to have children components have access to parent components method in VueJs

我有一個按鈕,它在我的父組件中執行表單驗證。 如果成功,此按鈕會呈現調用 API 的子組件。 問題是當我改變輸入時,顯示同時改變。 我試圖在父組件中使用animeFind 函數,以便我的子組件只負責 UI 並知道要顯示哪些數據(即有時 response.data["title"] 或 response.data["image_url"]。

父組件

<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"></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: {
    checkComplete() {
      if (this.anime1.length > 0 && this.anime2.length > 0) {
        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>

子組件

<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,
      // eslint-disable-next-line no-unused-vars
      handler(newVal, oldVal) {
        this.animeFind(newVal, "url1");
      },
    },
    anime2: {
      immediate: true,
      // eslint-disable-next-line no-unused-vars
      handler(newVal, oldVal) {
        this.animeFind(newVal, "url2");
      },
    },
  },
};
</script>

注意:我已經注釋掉了 axios 請求並始終返回一個圖像 url,以使這個示例在這里工作。

 Vue.component('compare-anim', { template: '#tmpl-compare-anim', data() { return { anime1: "", anime2: "", url1: "", url2: "" }; }, methods: { checkComplete() { if (this.anime1.length > 0 && this.anime2.length > 0) { this.animeFind(this.anime1, 'url1'); this.animeFind(this.anime2, 'url2'); } }, animeFind(anime, urlName) { var responseImg = this.makeRequest(anime); if (responseImg !== null) { this[urlName] = responseImg; } }, makeRequest(anime) { //Not gonna make axios request; returning sample image url //in order to test this implementation return "https://homepages.cae.wisc.edu/~ece533/images/monarch.png"; /** 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) => ( return response.data["image_url"]) ); }) .catch((error) => { this.error = error; // take care of this later return null; }); **/ } } }); Vue.component('render-anim', { template: '#tmpl-render-anim', props : { url1 : { default: function () { return ""; } }, url2 : { default: function () { return ""; } } }, methods: { } }); new Vue({ el: '#app', });
 <script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script> <div id="app"> <compare-anim></compare-anim> </div> <template id="tmpl-compare-anim"> <section class="hero"> <h1 class="title is-1">Compare two animes! :)</h1> <input placeholder="Enter the first anime!" v-model="anime1" /><br/><br/> <input placeholder="Enter the second anime!" v-model="anime2" /><br/><br/> <button class="button" type="is-primary" @click="checkComplete">Compare!</button> <render-anim :url1="url1" :url2="url2"></render-anim> </section> </template> <template id="tmpl-render-anim"> <section> <img :src="url1" v-if="url1" alt="./assets/notFound.png" width="100" /> <img :src="url2" v-if="url1" alt="./assets/notFound.png" width="100" /> </section> </template>

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM