- Html 的 表单 Form
-
结构复杂 - 需要指定 id 和 name
逻辑繁琐 - 需要大量事件参与
[] 留言板
<form action="https://www.baidu.com">
<input type="text" name="msg" placeholder="your message">
<button type="submit">submit</button>
</form>
表单常见事件类型
类型 |
说明 |
submit |
表单数据提交;默认会跳转,通常需阻止该行为 |
reset |
表单数据清除;各表单域值初始化 |
表单输入元素常见事件类型
类型 |
说明 |
focus |
获取焦点 |
blur |
失去焦点 |
change |
内容更改后触发,通常是更改后并失去焦点;如内容变化、选中状态变化等 |
input |
内容输入过程中触发 |
- Vue 的表单
-
需要借助 <form>这个壳
结构仍然比较复杂
没有突出数据驱动 Data Driven 的优点
- [] Vue 框架下一般方式
-
<form @submit="submit">
<input type="text" required maxlength="16" id="msg" name="msg" @input="doInput" @change="doChange"
@focus="doFocus" @blur="doBlur">
<br>
<label><input type="radio" id="male" name="gender" value="male" @change="doGenderMale">male</label>
<label><input type="radio" id="female" name="gender" value="female" @change="doGenderFemale">female</label>
<br>
<label><input type="checkbox" id="code" name="hobby" value="code" @change="doHobbyCode">code</label>
<label><input type="checkbox" id="sing" name="hobby" value="sing" @change="doHobbySing">sing</label>
<br>
<button type="submit">submit</button>
</form>
const submit = (event) => {
event.preventDefault();
console.log('Message:', msg.value);
console.log('Gender:', gender.value);
console.log('Hobbies:', hobbies.value);
};
const doInput = () => {
console.log('input', msg.value);
}
const doChange = () => {
console.log('change', msg.value);
}
const doFocus = () => {
console.log('focus', msg.value);
}
const doBlur = () => {
console.log('blur', msg.value);
}
const doGenderMale = () => {
console.log('radio', male.value, male.checked);
}
const doGenderFemale = () => {
console.log('radio', female.value, female.checked);
}
const doHobbyCode = () => {
console.log('checkbox', code.value, code.checked);
}
const doHobbySing = () => {
console.log('checkbox', sing.value, sing.checked);
}
-
v-bind:单向数据绑定:逻辑层数据流向渲染层
v-model:服务表单,实现
表单数据的双向绑定:将表单元素的内容同步给
JavaScript 中的数据:数据可以影响到表单;表单也可以影响到数据
数据可以是数值类型 number,也可以是字符串类型 string,还可以是布尔类型 true/false
绑定后会忽略任何表单元素上初始的 value、checked 或 selected 属性
使用开发者视图查看表单和表单元素的事件响应情况
元素 |
绑定属性 |
事件类型 |
<input> - text |
value 属性 |
input 事件 |
<textarea> |
value 属性 |
input 事件 |
<input> - radio |
checked 属性 |
change 事件 |
<input> - checkbox |
checked 属性 |
change 事件 |
<select> |
value 属性 |
change 事件 |
- [] 双向绑定
-
结构简单 - 可以省略 id、checked 等属性
响应式数据支持
根据需要指定默认值
根据需要采用其它事件
<form @submit.prevent="submit">
<input type="text" required maxlength="16" v-model="formData.msg">
<br>
<label><input type="radio" name="gender" v-model="formData.gender" value="male">male</label>
<label><input type="radio" name="gender" v-model="formData.gender" value="female">female</label>
<br>
<label><input type="checkbox" name="hobby" v-model="formData.hobby" value="code">code</label>
<label><input type="checkbox" name="hobby" v-model="formData.hobby" value="sing">sing</label>
<br>
<button type="submit">submit</button>
</form>
import { ref } from 'vue'
const formData = ref({
msg: '',
gender: 'male',
hobby: []
})
const submit = () => {
console.log('formData:', formData.value);
};
- <input> - text
-
单行文本输入 - 可以省略 id 和 name
绑定的是 value 属性 并侦听 input 事件
let msg = ref('')
<input type="text" v-model="msg" placeholder="your text here.">
<div>{{ msg }}</div>
传统方式 - 通过 input 事件和属性绑定实现双向绑定;这里采用内联事件|行内事件
<input type="text" @input="msg = $event.target.value" :value="msg" placeholder="your text here.">
<input type="text" @input="(e) => { msg = e.target.value }" :value="msg" placeholder="your text here.">
<div>{{ msg }}</div>
- <input> - radio
-
单选;多选一;不能单独使用
需要为每个 <radio> 指定值 value,并使用同一个名字 name 以确保它们是同一组
如果不指定 value,其默认值是 on - The default value for checkboxes and radio buttons is on
绑定的是 checked 属性 并侦听 change 事件
都绑定同一个值 value
let gender = ref('')
<input type="radio" name="gender" value="male" v-model="gender">male
<input type="radio" name="gender" value="female" v-model="gender">female
<div>Picked {{ gender }}</div>
传统方式 - 使用 change 事件获取
<input type="radio" name="gender" value="male" @change="(e) => gender = e.target.value">male
<input type="radio" name="gender" value="female" @change="(e) => gender = e.target.value">female
<div>{{ gender }}</div>
- <input> - checkbox
-
多选
绑定的是 checked 属性 并侦听 change 事件
需要为每个 <input> 指定值 value,并使用同一个名字 name 以确保它们是同一组
如果不指定 value,其默认值是 on - The default value for checkboxes and radio buttons is on
1. 单个:可以只使用一个多选按钮,绑定一个布尔值,用于确定选中与否的场合,如使用须知、用户协议等。这种情况下不需要指定具体的值
<input type="checkbox" v-model="isAgree"> 用户须知
const isAgree = ref(false)
2. 多个:为了区分选中的项目,必须指定值 value,且绑定同一个数组类型的值
let like = ref([])
<input type="checkbox" name="like" value="code" v-model="like">code
<input type="checkbox" name="like" value="sing" v-model="like">sing
<input type="checkbox" name="like" value="game" v-model="like">game
<input type="checkbox" name="like" value="read" v-model="like">read
<div>Checked items {{ like }}</div>
传统方式 - 使用 change 事件获取
<input type="checkbox" name="like" value="code" @change="sel">code
<input type="checkbox" name="like" value="sing" @change="sel">sing
<input type="checkbox" name="like" value="game" @change="sel">game
<input type="checkbox" name="like" value="read" @change="sel">read
<div>{{ like }}</div>
const sel = (e) => {
e.target.checked ? like.value.push(e.target.value) : like.value = like.value.filter(item => item !== e.target.value)
}
- <textarea>
-
多行输入;如:简介、留言、评论
绑定的是 value 属性 并侦听 input 事件
let msg = ref('')
<textarea v-model="msg" placeholder="edit your message"></textarea>
<div>{{msg}}</div>
不可以使用内容绑定的插值表达式 {{}}
<textarea v-model="msg" required>{{msg}}</textarea>
传统方式 - 通过 input 事件和属性绑定实现
<textarea @input="(e) => { msg = e.target.value }" :value="msg" required></textarea>
<div>{{msg}}</div>
- <select>
-
下拉列表;下拉框
绑定的是 value 属性 并侦听 change 事件
注意提示信息的处理:空值、选中、禁用
let sel = ref('')
<select v-model = 'sel'>
<option disabled selected value="">请选择</option>
<option value='1'>1</option>
<option value='2'>2</option>
<option value='3'>3</option>
</select>
<div>selected {{sel}}</div>
- Summary
-
<input> 的 text 类型:绑定 value 属性;侦听 input 事件
<textarea>:绑定 value 属性;侦听 input 事件
<input> 的 radio 类型:绑定 checked 属性;侦听 change 事件
<input> 的 checkbox 类型:绑定 checked 属性;侦听 change 事件
<select>:绑定 value 属性;侦听 change 事件
数据应该是唯一的
数据的调试和检查
-
实现双向绑定后,可以忽略 <form> 这个壳,直接在 <button>的事件上提交数据
实现绑定后,更多需求仍然需要事件的支持,如 change 后根据状态变化执行相应的逻辑
双向绑定引发的性能问题
建议通过组件封装实现
- Homework
- [] 留言板 - 按 Ctrl + Enter 提交留言;这里使用 <input> 实现
-
方案1:使用双向数据绑定
1.1 使用 <form> 这个壳,采用按钮的默认单击事件触发表单数据提交
<form @submit.prevent="submit">
<input type="text" v-model.trim="msg" placeholder="your message">
<button type="submit">submit</button>
</form>
const msg = ref('');
const submit = () => {
console.log(msg.value)
};
1.2 不使用 <form> 这个壳,使用单击 - 按钮 button
<input type="text" v-model.trim="msg" placeholder="your message">
<button @click="submit">submit</button>
1.3 不使用 <form> 这个壳,使用按键事件 - 输入框 input
<input type="text" v-model.trim="msg" @keyup.ctrl.enter="submit" placeholder="your message">
方案2:传统方式
不需要 <form> 这个壳
不需要声明数据
2.1 使用 id
<input type="text" @keyup.ctrl.enter="submit" placeholder="your message" id="msg">
const submit = () => {
console.log('ctrl enter submit')
console.log(msg.value);
}
2.2 使用事件对象 target
<input type="text" @keyup.ctrl.enter="submit" placeholder="your message">
const keySubmit = (e) => {
console.log('ctrl enter submit')
console.log(e);
console.log(e.key);
console.log(e.keyCode);
console.log(e.target.value);
}
- [] 登录页 LoginView.vue
-
1. 提示信息的显示与隐藏 - 获取焦点时,且不为空时显示提示信息
方案1:使用 v-show
<div class="item">
<input type="text" v-model.trim.lazy="user.name" required maxlength="11"
@focus="isFocus = true"
@blur="isFocus = false">
<span class="tips" v-show="isFocus && !user.name">请输入手机号</span>
</div>
.tips {
position: absolute;
top: 0;
left: 20px;
color: #666;
line-height: 40px;
}
方案2:使用动态类 - 一开始隐藏,激活时显示
<div class="item">
<input type="text" v-model.trim="user.name" required maxlength="11"
@focus="isFocus = true"
@blur="isFocus = false">
<span class="tips" :class="{ 'active': isFocus && !user.name }">请输入手机号</span>
</div>
.tips {
position: absolute;
top: 0;
left: 20px;
color: #666;
line-height: 40px;
}
.tips-name.active {
display: block;
}
2. 使用须知、记住密码
使用单个复选框实现;不需要指定 value,需要的只是是否选中
let isAgree = ref(false)
<label>
<input type="checkbox" v-model="isAgree"> 已阅读并同意服务条款
</label>
- [] 商品详情页 DetailsView.vue
-
产品规格 specification
甜点推荐 RecoDessert.vue