-
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
let msg = ref('')
<input type="text" v-model="msg" required>
<div>{{ msg }}</div>
传统方式 - 通过 input 事件和属性绑定实现双向绑定;这里采用内联事件|行内事件
<input type="text" @input="msg = $event.target.value" :value="msg" required>
<input type="text" @input="(e) => { msg = e.target.value }" :value="msg" required>
<div>{{ msg }}</div>
- <input> - radio
-
单选;多选一
需要为每个 <radio> 指定值 value,并使用同一个名字 name 以确保它们是同一组
不指定 value 的话,只能获取单选框的选中状态 checked 是 true 还是 false,并不知道选择了谁
let gender = ref('')
双向绑定 - 选中都绑定 gender,同时指定值 value
<input type="radio" name="gender" value="male" v-model="gender">male
<input type="radio" name="gender" value="female" v-model="gender">female
<div>{{ 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
-
多选
需要为每个 <input> 指定值 value,并使用同一个名字 name 以确保它们是同一组
如果不指定 value,只能获取复选框的选中状态 checked 是 true 还是 false,并不知道选择了谁 - 可用于状态判断,如是否同意、是否阅读等用户须知场合
let like = ref([])
双向绑定 - 选项都绑定数据 like,同时指定值 value
<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>{{ 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)
}
-
<input>的 radio 类型和 checkbox 类型,绑定的是 checked 属性 并侦听 change 事件
如果不指定 value,其默认值是 on - The default value for checkboxes and radio buttons is on
- <textarea>
-
多行输入;留言、评论
let msg = ref('')
双向绑定
<textarea v-model="msg" required></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>
- <input> 的 text 类型和 <textarea>,绑定的是 value 属性 并侦听 input 事件
- <select>
-
下拉列表;下拉框
let sel = ref('')
<select v-model = 'sel'>
<option value='1'>1</option>
<option value='2'>2</option>
<option value='3'>3</option>
</select>
<div>{{sel}}</div>
- <select> 绑定的是 value 属性 并侦听 change 事件
- 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 提交留言
-
适合桌面端
方案1:使用双向数据绑定
不需要 <form> 这个壳
使用修饰符 lazy
<input type="text" v-model.lazy="msg">
import { ref } from 'vue'
const msg = ref('')
方案2:使用按键事件实现 - 查看并分析事件对象
不需要 <form> 这个壳
需要指定 id
<input type="text" @keyup.ctrl.enter="keySubmit" placeholder="your text" id="msg">
const keySubmit = (e) => {
console.log('ctrl enter submit')
console.log(e);
console.log(e.key);
console.log(e.keyCode);
console.log(msg.value);
}
- [] 登录页 LoginView.vue
-
1. 提示信息的显示与隐藏
方案1:使用 v-show
<div class="item">
<input type="text" v-model.trim="user.name" required maxlength="11"
@focus="isFocus = true"
@blur="isFocus = false">
<span class="tips tips-name" v-show="isFocus && !user.name">请输入手机号</span>
</div>
.tips {
position: absolute;
top: 0;
color: #666;
line-height: 40px;
}
.tips-name {
left: 20px;
}
方案2:使用动态类 - 一开始隐藏,激活时显示
<div class="item">
<input type="text" v-model.trim="user.name" required maxlength="11"
@focus="isFocus = true"
@blur="isFocus = false">
<span class="tips tips-name" :class="{ 'active': isFocus && !user.name }">请输入手机号</span>
</div>
.tips {
position: absolute;
top: 0;
color: #666;
line-height: 40px;
}
.tips-name {
left: 20px;
display: none;
}
.tips-name.active {
display: block;
}
2. 使用须知、记住密码
使用单个复选框实现;不需要指定 value,需要的只是是否选中
let isAgree = ref(false)
<label>
<input type="checkbox" v-model="isAgree"> 已阅读并同意服务条款
</label>
- [] 注册
- [] 商品详情页 DetailsView.vue
-
产品规格 specification
甜点推荐 RecoDessert.vue