【问题标题】:unable to change data values when using $emit on an object in vue在 vue 中的对象上使用 $emit 时无法更改数据值
【发布时间】:2020-04-16 08:39:11
【问题描述】:

使用$emitchildparent 组件之间进行通信。我在子组件中有一个方法,它在 api 调用的不同阶段触发 $emit。即,在进行 api 调用之前,我需要向父级发送一些值以禁用父级中的某些字段。所以使用$emit 发送这些值并且它成功地工作。但是,当我以相同的方法从 api 获取结果后尝试调用相同的 $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>

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

【问题讨论】:

  • 1.您的代码框不起作用。你能修好它吗? 2. 只是快速浏览后的猜测,但尝试将this.otpInput = value; 更改为this.otpInput = { ...this.otpInput, ...value };
  • @AdamOrlov 代码仍然无法正常工作。我不知道为什么codeandbox 不工作。以前从未使用过。这些更改不会在代码框的预览中复制。对此感到抱歉。
  • @AdamOrlov 代码框现在可以正常工作,演示也可以正常工作 web url 20unr.sse.codesandbox.io
  • 你修好了吗? console.log("called") 被调用
  • @LawrenceCherone 不。即使它正确地发出,父状态在 $emit 的第二次调用中也没有改变

标签: vue.js vuejs2 vue-component


【解决方案1】:

第一次调用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 次​​p>

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

(注意isOtpMode: true

我认为你应该在第一次调用中保持isOtpMode 为真,并使用isVerifying 来禁用父组件中的某些内容。

演示here

【讨论】:

  • 我花了 2 天时间。我认为与状态更新有关的事情是在更新父对象中的对象。非常感谢朋友。
猜你喜欢
  • 2021-06-19
  • 1970-01-01
  • 1970-01-01
  • 2017-12-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-03-01
  • 1970-01-01
相关资源
最近更新 更多