Vuejs 将动态数据从父组件传递到子组件

时间:2021-01-18 06:18:30

标签: vue.js

我有一个视图和一个组件。我正在尝试在这里进行身份验证。

作为用户,我输入用户名和密码,点击login。这 emits 父组件的信息,它向 AWS 中的 API 网关发出提取请求。此提取响应具有我感兴趣的标头 X-Session-Id

我的 emit 部分工作正常。

但是,我无法将标头值传递回组件,并且无法将 new_password_required 设置为 true,这会为新密码添加新的输入字段,以及将 login button 替换为 reset password 按钮。

我觉得我需要用道具来做这件事,但我无法成功地将值从父级传递给子级。

另外,重置密码位应该有自己的组件吗?

下面是我的代码。这是我的第一个前端,所以我不熟悉我应该如何共享它(例如在操场上)。另外,我现在正在尝试坚持使用 vanilla vue,因为我正在学习(我认为我只安装了 vue-router)

<template>
  <div id="app" class="small-container">
    <login-form @login:user="loginUser($event)" />
  </div>
</template>

<script>
import LoginForm from "@/components/LoginForm.vue";

export default {
  name: "Login",
  components: {
    LoginForm
  },
  data() {
    return {
      session_id: String,
      new_password_required: Boolean
    };
  },
  methods: {
    async loginUser(loginEvent) {
      try {
        const response = await fetch(
          process.env.VUE_APP_API_GATEWAY_ENDPOINT + "/login/user",
          {
            method: "POST",
            body: JSON.stringify(loginEvent)
          }
        );
        const data = await response.json();
        console.log(data);
        if (data.headers["X-Session-Id"] != null) {
          this.session_id = data.headers["X-Session-Id"];
          this.new_password_required = true;
        }
      } catch (error) {
        console.error(error);
      }
    },
    async resetPassword(resetPasswordEvent) {
      try {
        const response = await fetch(
          process.env.VUE_APP_API_GATEWAY_ENDPOINT + "/reset/user/password",
          {
            method: "POST",
            body: JSON.stringify(resetPasswordEvent)
          }
        );
        const data = await response.json();
        console.log(data);
      } catch (error) {
        console.error(error);
      }
    }
  }
};
</script>

组件

<template>
  <div id="login-form">
    <h1>Serverless App</h1>
    <form>
      <label for="email_address">Email Address:</label><br />
      <input
        v-model="login_details.email_address"
        type="text"
        id="email_address"
        name="email_address"
      /><br />
      <label for="password">Password:</label><br />
      <input
        v-model="login_details.password"
        type="password"
        id="password"
        name="password"
      />
      <label v-if="new_password_required" for="new_password"
        >New Password:</label
      ><br />
      <input
        v-if="new_password_required"
        v-model="login_details.new_password"
        type="password"
        id="new_password"
        name="new_password"
      />
    </form>
    <button v-if="!new_password_required" @click="loginUser($event)">
      Login
    </button>
    <button v-if="new_password_required" @click="resetPassword($event)">
      Reset Password
    </button>
  </div>
</template>

<script>
export default {
  name: "LoginForm",
  props: {
    session_id: String,
    new_password_required: {
      type: Boolean,
      default: () => false
    }
  },
  data() {
    return {
      login_details: {
        email_address: "",
        password: "",
        new_password: ""
      }
    };
  },

  methods: {
    loginUser() {
      console.log("testing loginUser...");
      const loginEvent = {
        email_address: this.login_details.email_address,
        password: this.login_details.password
      };
      this.$emit("login:user", loginEvent);
    },

    resetPassword() {
      console.log("testing resetPassword...");
      const resetPasswordEvent = {
        email_address: this.login_details.email_address,
        password: this.login_details.password,
        new_password: this.login_details.new_password,
        session_id: this.login_details.sessionId
      };
      this.$emit("reset:Password", resetPasswordEvent);
    }
  }
};
</script>

2 个答案:

答案 0 :(得分:1)

您的子组件看起来不错,但是,您需要在父组件中传递道具,如下所示:

<login-form @login:user="loginUser($event)" :session-id="xidhere"
    :new-password-required="newPasswordRequired"/>

当这些值在父组件中更新时,子组件也应该更新。

注意,使用驼峰命名法命名道具,然后在 HTML 中使用 kebab-case。

因此您的登录表单道具应更新为:

  props: {
    sessionId: String,
    newPasswordRequired: {
      type: Boolean,
      default: () => false
    }
  },

此外,当您将事件发送给父级时,可能不需要将会话 ID 发送给子级,只需在发送之前将其添加到您的 api 调用中即可。

答案 1 :(得分:0)

想通了。我创建了一个新的子组件来重置密码。也许它可以干一点?我是新手。很高兴得到任何指点:)

父母

<template>
  <div id="app" class="small-container">
    <login-form v-if="!new_password_required" @login:user="loginUser($event)" />
    <reset-password-form
      v-if="new_password_required"
      :session_id="session_id"
      @reset:password="resetPassword($event)"
    />
  </div>
</template>

<script>
import LoginForm from "@/components/LoginForm.vue";
import ResetPasswordForm from "@/components/ResetPasswordForm.vue";

export default {
  name: "Login",
  components: {
    LoginForm,
    ResetPasswordForm
  },
  data() {
    return {
      session_id: "",
      new_password_required: false
    };
  },
  methods: {
    async loginUser(loginEvent) {
      try {
        const response = await fetch(
          process.env.VUE_APP_API_GATEWAY_ENDPOINT + "/login/user",
          {
            method: "POST",
            body: JSON.stringify(loginEvent)
          }
        );
        const data = await response.json();
        console.log(data);
        if (data.headers["X-Session-Id"] != null) {
          this.session_id = data.headers["X-Session-Id"];
          this.new_password_required = true;
        }
      } catch (error) {
        console.error(error);
      }
    },

    async resetPassword(resetPasswordEvent) {
      try {
        const response = await fetch(
          process.env.VUE_APP_API_GATEWAY_ENDPOINT + "/reset/user/password",
          {
            method: "POST",
            body: JSON.stringify(resetPasswordEvent)
          }
        );
        const data = await response.json();
        console.log(data);
      } catch (error) {
        console.error(error);
      }
    }
  }
};
</script>

儿童:登录表单

<template>
  <div id="login-form">
    <h1>Serverless Release Dashboard</h1>
    <form>
      <label for="email_address">Email Address:</label><br />
      <input
        v-model="login_details.email_address"
        type="text"
        id="email_address"
        name="email_address"
      /><br />
      <label for="password">Password:</label><br />
      <input
        v-model="login_details.password"
        type="password"
        id="password"
        name="password"
      />
    </form>
    <button @click="loginUser($event)">
      Login
    </button>
  </div>
</template>

<script>
export default {
  name: "LoginForm",
  data() {
    return {
      login_details: {
        email_address: "",
        password: ""
      }
    };
  },

  methods: {
    loginUser() {
      console.log("testing loginUser...");
      const loginEvent = {
        email_address: this.login_details.email_address,
        password: this.login_details.password
      };
      this.$emit("login:user", loginEvent);
    }
  }
};
</script>

儿童:reset-password-form

<template>
  <div id="reset-password-form">
    <h1>Serverless Release Dashboard</h1>
    <form>
      <label for="email_address">Email Address:</label><br />
      <input
        v-model="login_details.email_address"
        type="text"
        id="email_address"
        name="email_address"
      /><br />
      <label for="password">Password:</label><br />
      <input
        v-model="login_details.password"
        type="password"
        id="password"
        name="password"
      />
      <label for="new_password">New Password:</label><br />
      <input
        v-model="login_details.new_password"
        type="password"
        id="new_password"
        name="new_password"
      />
    </form>
    <button @click="resetPassword($event)">
      Reset Password
    </button>
  </div>
</template>

<script>
export default {
  name: "ResetPasswordForm",

  props: {
    email_address: String,
    password: String,
    session_id: String
  },

  data() {
    return {
      login_details: {
        email_address: "",
        password: "",
        new_password: "",
        session_id: ""
      }
    };
  },

  methods: {
    resetPassword() {
      console.log("testing resetPassword...");

      const loginEvent = {
        email_address: this.email_address,
        password: this.password,
        new_password: this.login_details.new_password,
        session_id: this.session_id
      };
      this.$emit("reset:password", loginEvent);
    }
  }
};
</script>