如何让子组件可以访问VueJs中的父组件方法

时间:2020-09-26 03:16:32

标签: javascript html vue.js vuejs2

我在父组件中有一个用于执行表单验证的按钮。如果成功,此按钮将呈现一个调用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>

1 个答案:

答案 0 :(得分:0)

注意: 我已注释掉axios请求并返回了图像 网址,始终使该示例在这里工作。

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>