Vue 3.0教程(for beginner):Forms&Inputs

213 阅读3分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第10天,点击查看活动详情

submit.gif

前言

结合前面的教程Vue 3.0教程(for beginner):Vue Cli(上篇),基于vue-cli创建一个web-form项目应用

image.png

删掉其中无用的组件和内容,将App.vue组件内容替换为:

<template>
  <SignupForm></SignupForm>
</template>

<script>
import SignupForm from './components/SignupForm.vue'
export default {
  name: 'App',
  components: { SignupForm },
}
</script>

SignupForm则是我们要创建的表单组件。在components目录新建SignupForm.vue文件,填充内容为:

<template>
  <form>
    <label>邮箱:</label>
    <input type="email" required />
  </form>
</template>

<script>
export default {
  name: 'SignupForm',
}
</script>

结合一些自定义的css样式,我们看到如下效果:

image.png

接着,我们开始书写表单组件内的逻辑。

两种数据绑定的方式

  1. 使用v-model获取用户输入的表单值:
<template>
  <form>
    <label>邮箱:</label>
    <input type="email" required v-model="email" />
    <label>密码:</label>
    <input type="password" required v-model="password" />
  </form>
  <p>邮箱: {{ email }}</p>
  <p>密码: {{ password }}</p>
</template>

<script>
export default {
  name: 'SignupForm',
  data() {
    return {
      email: '',
      password: '',
    }
  },
}
</script>

这里另外新增了一个密码输入框,同时分别用两个变量emailpassword保存输入的值,并在最后输出的页面。

image.png

通过v-model指令,将输入框的值与eamil等变量进行绑定,程序可以正确获取到输入值并显示(到其他地方),这其实就是vue的数据双向绑定。

我们也可以给邮箱设置一个默认值:

<template>
  <form>
    <label>邮箱:</label>
    <input type="email" required v-model="email" />
    <label>密码:</label>
    <input type="password" required v-model="password" />
    <label>角色:</label>
    <select v-model="role">
      <option value="开发">开发</option>
      <option value="产品">产品</option>
    </select>
  </form>
  <p>邮箱: {{ email }}</p>
  <p>密码: {{ password }}</p>
  <p>角色: {{ role }}</p>
</template>

<script>
export default {
  name: 'SignupForm',
  data() {
    return {
      email: '',
      password: '',
      role: '开发',
    }
  },
}
</script>

image.png

这里增加了一个select选择框并绑定了role变量,同时给它设置了初始值。

Checkbox

前面展示了inputselect组件的用法,接着我们继续看checkbox的使用:

<template>
  <form>
    // ...省略
    <div class="terms">
      <input type="checkbox" v-model="terms" required />
      <label>同意条款</label>
    </div>
  </form>
  // ...省略
  <p>条款: {{ terms }}</p>
</template>

<script>
export default {
  name: 'SignupForm',
  data() {
    return {
      email: '',
      password: '',
      role: '开发',
      terms: false,
    }
  },
}
</script>

image.png

上面展示的是单个checkbox的情形,如果有多个复选框支持多选,要如何做呢?

<template>
  <form>
    // ...
    <div class="terms">
      <input type="checkbox" v-model="terms" required />
      <label>同意条款</label>
    </div>
    <div>
      <input type="checkbox" value="javascript" v-model="langs" />
      <label>javascript</label>
    </div>
    <div>
      <input type="checkbox" value="css" v-model="langs" />
      <label>css</label>
    </div>
    <div>
      <input type="checkbox" value="html" v-model="langs" />
      <label>html</label>
    </div>
  </form>
  // ...
  <p>语言: {{ langs }}</p>
</template>

<script>
export default {
  name: 'SignupForm',
  data() {
    return {
      email: '',
      password: '',
      role: '开发',
      terms: false,
      langs: [],
    }
  },
}
</script>

我们使用一个数组变量langsv-model进行绑定,vue程序会自动帮我们把选中的值push进数组中,及其方便。 image.png

键盘事件

为演示键盘事件的绑定,这里新增了一个技能项,绑定了键盘按键弹起事件keyup,并在addSkill里面处按键事件的逻辑,仅当用户按下Enter键时才处理用户输入的内容,收集并打印出来:

<template>
  <form>
    // ...
    <label>技能:</label>
    <input type="text" v-model="skill" @keyup="addSkill" />
    <div class="skills">
      <span v-for="item in skills" :key="item">{{ item }}</span>
    </div>
    <div class="terms">
      <input type="checkbox" v-model="terms" required />
      <label>同意条款</label>
    </div>
  </form>
  // ...
</template>

<script>
export default {
  name: 'SignupForm',
  data() {
    return {
      // ...
      skill: '',
      skills: [],
    }
  },
  methods: {
    addSkill(e) {
      if (e.key === 'Enter' && this.skill) {
        this.skills.push(this.skill)
        this.skill = ''
      }
    },
  },
}
</script>

image.png

addSkill事件中,我们通过e.key === 'Enter'过滤了键盘事件,但在vue的鼠标事件中,它支持事件修饰符,通过绑定enter事件修饰符,能够达到同样的目的效果:

<input type="text" v-model="skill" @keyup.enter="addSkill" />

小挑战:删除技能项

我们给每个技能项绑定一个点击事件,在点击的时候删除该技能:

<div class="skills">
  <span v-for="item in skills" :key="item" @click="deleteSkill(item)">{{
    item
  }}</span>
</div>

处理事件deleteSkill

<script>
export default {
  name: 'SignupForm',
  // ...
  methods: {
    // ...
    deleteSkill(skill) {
      this.skills = this.skills.filter((v) => {
        return skill !== v
      })
    },
  },
}
</script>

表单提交

最后,我们需要提交创建的表单,form支持@submit事件去提交表单:

<template>
  <form @submit.prevent="handleSubmit">
    <label>邮箱:</label>
    <input type="email" required v-model="email" />
    <label>密码:</label>
    <input type="password" required v-model="password" />
    <div class="error" v-if="passwordError">{{ passwordError }}</div>
    
    // ...
    
    <div class="submit">
      <button>创建账户</button>
    </div>
  </form>
  // ...
</template>

<script>
export default {
  name: 'SignupForm',
  data() {
    return {
      // ...
      passwordError: '',
    }
  },
  methods: {
    // ...
    handleSubmit() {
      // 校验密码
      this.passwordError = this.password.length > 5 ? '' : '密码至少6位'
      if (!this.passwordError) {
        alert('提交成功!')
      }
    },
  },
}
</script>

在提交表单事件中,我们增加了一个prevent事件修饰符,它表示阻止表单的默认行为,这样我们才能在handleSubmit方法中处理表单提交的行为,否则表单会刷新提交,无法进入handleSubmit的事件处理程序中。

submit.gif

未完待续Vue 3.0教程(for beginner): 路由