如何创建 Vuejs 控制的输入表单?

How to create Vuejs controlled input form?

我习惯于使用状态在 React 中创建受控组件;但是,我是 Vue 的新手,想了解如何将我的代码从 React 重新创建为 Vue 可以使用的东西。我希望将输入字段值存储在一段数据中,以便我可以对它们进行一些处理。

<template>
    <form @submit="handleSubmit" class="form form--signin">
        <h2 class="form__h2">Log into your account</h2>

        <label for="email">Email address</label>
        <input v-model="email" type="email" id="email" autoComplete="off"/>

        <label for="password">Password</label>
        <input v-model="password" type="password" id="password" autoComplete="off"/>

        <button class="form__btn">Login</button>
    </form>
</template>

<script>

从 'axios' 导入 axios;

export default {
    name: 'SignIn',
    data() {
        return {
            user: null,
            email: null,
            password: null
        }
    },
    methods: {
        handleSubmit(event) {
            event.preventDefault();
            this.login(this.email, this.password);
            this.email = '';
            this.password = '';
        },
        login(email, password) {
            axios.post('http://localhost:8000/api/v1/users/login', {
                email,
                password
            })
            .then(res => {
                // console.log(this.user);
                this.user = res.data.data.user;
                if(res.data.status === 'success') {
                    // setUserStatus(res.data.status);
                    window.setTimeout(() => {
                        window.location.assign('/');
                    }, 1500)
                }
            })
            .catch(err => console.log(err.response.data.message));
        }
    }, 
    mounted() {
        if (!this.user) return;

        console.log('Writing to session storage...');
        sessionStorage.setItem('user', JSON.stringify(this.user));
    }
}

这是 Vue

中的样子

Vue.config.devtools = false;
Vue.config.productionTip = false;

const SignIn = Vue.component('sign-in', {

  template: `<form @submit="handleSubmit" className="form form--signin">
            <h2 className="form__h2">Log into your account</h2>

            <label htmlFor="email">Email address</label>
            <input v-model="email" type="email" id="email" autoComplete="off"/>

            <label htmlFor="password">Password</label>
            <input v-model="password" type="password" id="password" autoComplete="off"/>

            <button className="form__btn">Login</button>
        </form>`,
  data() {
    return {
      user: null,
      email: null,
      password: null,
    }
  },
  methods: {
    handleSubmit(event) {

      this.login(this.email, this.password)
      this.email = '';
      this.password = '';
      
      event.preventDefault();
    },
    login(email, password) {

    }
  },
  mounted() {
    if (!this.user)
      return;

    console.log('Writing to session storage...');
    sessionStorage.setItem('user', JSON.stringify(user));
  }
})

var app = new Vue({
  el: '#app'
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
  <sign-in></sign-in>
</div>

这就是我在 Vue 中编写相同组件的方法:

<template>
  <form @submit.prevent="handleSubmit" class="form form--signin">
    <h2 class="form__h2">Log into your account</h2>

    <label for="email">Email address</label>
    <input v-model="email" type="email" id="email" autocomplete="off">

    <label for="password">Password</label>
    <input v-model="password" type="password" id="password" autocomplete="off">

    <button class="form__btn">Login</button>
  </form>
</template>

<script>
const login = async (email, password) => {
  // make the api call and return a promise
};

export default {
  name: "SignIn",
  data: () => ({
    email: "",
    password: ""
  }),
  methods: {
    async handleSubmit(event) {
      console.log("Getting user from API...");

      try {
        const user = await login(this.email, this.password);

        console.log("Writing to session storage...");
        sessionStorage.setItem("user", JSON.stringify(user));

        this.email = "";
        this.password = "";
      } catch (e) {
        // handle login errors
      }
    }
  }
};
</script>

表单控件的状态存储在组件的 data 属性 中,并使用 v-model 指令在控件上设置双向绑定。对输入的任何更改都将同步到组件的状态,反之亦然。

Vue 在向模板添加事件侦听器时提供了一些方便的修饰符,因此通过编写 @submit.prevent 可以防止触发默认提交处理程序。

我创建了一个 sandbox example,因此您可以轻松地使用代码并查看它的实际效果。

您可以使用 v-model directive to bind component data and v-on 指令来绑定组件方法:

<template>
  <div>
    <div class>Login Form</div>

    <form v-on:submit="handleSubmit">
      <input v-model="email" placeholder="email" type="text" class="input" />
      <br />
      <input v-model="password" placeholder="password" type="password" class="input" />
      <br />
      <button v-on:click="handleSubmit" type="submit" class="submit">Login</button>
    </form>

    <hr />

    <div>Email: {{email}} and Password: {{password}}</div>
    <div>User sessions: {{user}}</div>
  </div>
</template>

并且可以使用 axios 进行 API 调用以验证和存储来自响应的 user 会话数据:

<script>
import axios from "axios";
export default {
  name: "LoginForm",
  props: {},
  data: () => ({
    email: "",
    password: "",
    user: {}
  }),
  methods: {
    login() {
      axios
        .post("http://localhost:8000/api/v1/users/login", {
          email: this.email,
          password: this.password
        })
        .then(res => {
          console.log(res);
          this.user = res.data.data.user;
          sessionStorage.setItem("user", JSON.stringify(this.user));
          if (res.data.status === "success") {
            window.setTimeout(() => {
              window.location.assign("/"); // to verify mounted hook
            }, 1500);
          }
        })
        .catch(err => console.log(err.response.data.message));
    },
    handleSubmit: function(e) {
      e.preventDefault();
      this.login();
    }
  },
  mounted() {
    console.debug("mounted");
  }
};
</script>

此外,请注意您可以使用 mounted lifecycle hookslocalStorage 或您选择的任何其他地方读取数据。

您可以使用 async / await 或 then / catch 来处理异步(基于承诺的)API 调用。

这里是CodeSandbox.


下面是如何在 React 中使用 mounted 钩子,与 useEffect(() => {}, []) 相同:

mounted() {
    const user = sessionStorage.getItem("user");
    if (user) {
      this.user = JSON.parse(user);
    }
  }