首页 > 解决方案 > 在 vue 中的对象上使用 $emit 时无法更改数据值

问题描述

用于组件之间的$emit通信。我在子组件中有一个方法,它在调用的不同阶段触发 $emit 。即,在进行 api 调用之前,我需要向父级发送一些值以禁用父级中的某些字段。因此,用于发送这些值并且它可以成功运行。但是,当我以相同的方法从 api 获取结果后尝试调用相同的 $emit 事件时,它没有得到更新。这些值已成功从子级发出,但在父级中它仅在第一次更新。childparentapi$emit

这是父组件

<template>
  <div>
    <div class="horizontal-fields">
      <input
        id="General_mobile"
        class="input-fied"
        name="mobileNumber"
        placeholder="Enter your mobile"
        type="number"
        autocomplete="new mobile"
        :disabled="otpInput.isVerifying"
      >
      <input @click.prevent="sendVerificationCode" value="sendotp" class="otp-btn" type="button">
    </div>

    <div v-if="otpInput.isOtpMode">
      <GeneralOtp
        :message="otpGeneratedMessage"
        :mobileNumber="this.mobileNumber"
        @handleComplete="handleCompleteOtp"
      />
    </div>
  </div>
</template>

<script>
import axios from "axios";
import GeneralOtp from "./GeneralOtp";

export default {
  name: "MobileVerification",
  components: {
    GeneralOtp
  },
  data() {
    return {
      mobileNumber: null,
      isValidMobile: null,
      buttonValue: "Send OTP",
      otpGeneratedMessage: null,
      otpInput: {
        isOtpMode: false,
        isVerifying: false,
        otpToken: null,
        currentVerifiedMobile: null
      }
    };
  },
  methods: {
    async sendVerificationCode() {
      const { data } = await axios.get(
        "https://jsonplaceholder.typicode.com/todos/1"
      );
      if (data.userId) {
        this.otpGeneratedMessage = "some message from server";
        this.otpInput.isOtpMode = true; //to show otp input field(child component)
      }
    },
    handleCompleteOtp(value) {
      console.log("called");
      this.otpInput = value;
    }
  }
};
</script>

这是子组件

    <template>
  <div>
    <div v-if="!isVerifying">
      <input id="otp" class="input-fied" name="otpcode" placeholder="Enter your otp" type="number">
      <input @click.prevent="this.verifyOtp" value="buttonValue" class="otp-btn" type="button">
      <p style="margin-top: 2%">{{ message }}</p>
    </div>
    <div v-else="isVerifying">
      <p>Please wait</p>
    </div>
  </div>
</template>

<script>
import axios from "axios";

export default {
  props: {
    message: {
      type: String,
      default: ""
    },
    mobileNumber: {
      type: String,
      default: null
    }
  },
  data() {
    return {
      isVerifying: false
    };
  },
  methods: {
    async verifyOtp() {
      /* Disable inputs & show loading */
      this.isVerifying = true;
      this.respondToParent({
        otpToken: null,
        mobileNumber: this.mobileNumber,
        isVerifying: this.isVerifying,
        isOtpMode: false
      });

      /* Send verify request to server */
      const { data } = await axios.get(
        "https://jsonplaceholder.typicode.com/todos/1"
      );
      /* If success & valid hide in parent send verified flag to parent */
      /* If success & invalid otp show error */
      this.isVerifying = false;
      if (data.userId) {
        this.respondToParent({
          otpToken: "token from a success response",
          mobileNumber: this.mobileNumber,
          isVerifying: false,
          isOtpMode: false
        });
      } else {
        this.respondToParent({
          OtpToken: null,
          mobileNumber: this.mobileNumber,
          isVerifying: this.isVerifying,
          isOtpMode: false
        });
      }
      /* If error show retry button with error message */
    },

    respondToParent(value) {
      this.$emit("handleComplete", {
        otpToken: value.otpToken,
        mobileNumber: this.mobileNumber,
        isVerifying: value.isVerifying,
        isOtpMode: value.isOtpMode
      });
    }
  }
};
</script>

我无法弄清楚为什么它没有第二次更新,即使它两次都被孩子调用。不知何故设法在沙盒环境中复制了相同的内容。 密码箱中的代码

标签: vue.jsvuejs2vue-component

解决方案


第一次调用this.respondToParent时,它设置otpInput.isOtpMode为 false,因此GeneralOtp不会渲染,因为您使用的是 v-if:

<div v-if="otpInput.isOtpMode">
  <GeneralOtp
    :message="otpGeneratedMessage"
    :mobileNumber="this.mobileNumber"
    @handleComplete="handleCompleteOtp"
  />
</div>

this.respondToParent如果您将第一个更改为,您可以检查它将被调用 2 次

  this.respondToParent({
    otpToken: null,
    mobileNumber: this.mobileNumber,
    isVerifying: this.isVerifying,
    isOtpMode: true
  });

(请注意isOtpMode: true

我认为您应该isOtpMode在第一次通话中保持真实,并使用isVerifying您所说的禁用父组件中的某些内容。

演示在这里


推荐阅读