小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。
1. v-model 绑定其它表单元素
除了绑定 type="text" 的 <input> 元素,v-model 还可以绑定 <textarea> 元素、type="checkbox" 的 <input> 元素、type="radio" 的 <input> 元素以及 <select> 元素。
1.1 绑定 <textarea> 元素
与绑定 type="text" 的 <input> 元素的做法类似:
<label for="introduction">
自我介绍:
<textarea id="introduction" v-model="intro" cols="30" rows="10"></textarea>
</label>
<h2>intro: {{ intro }}</h2>
data() {
return {
intro: 'Hello World'
}
}
1.2 绑定 type="checkbox" 的 <input> 元素
第一种情况是单选框,即只有一个 type="checkbox" 的 <input> 元素,v-model 绑定之后的最终结果是一个布尔值(true/false):
<label for="agreement">
<input id="agreement" type="checkbox" v-model="isAgree"> 同意协议
</label>
<h2>isAgree: {{ isAgree }}</h2>
data() {
return {
isAgree: false
}
}
第二种情况是多选框,即有多个 type="checkbox" 的 <input> 元素,可以选择多个值,这时这些 <input> 元素上的 v-model 需要绑定到同一个属性,但它们的 value 属性值则应该各不相同,因为选中的 <input> 元素的值就是这些 value 属性的值,并且最终会被加入到一个数组中去:
<span>爱好:</span>
<label for="basketball">
<input id="basketball" type="checkbox" v-model="hobbies" value="basketball"> 篮球
</label>
<label for="football">
<input id="football" type="checkbox" v-model="hobbies" value="football"> 足球
</label>
<label for="volleyball">
<input id="volleyball" type="checkbox" v-model="hobbies" value="volleyball"> 排球
</label>
<h2>hobbies: {{ hobbies }}</h2>
data() {
return {
hobbies: []
}
}
补充:
<p>
<input type="checkbox" id="sleep-cbox" v-model="isChecked">
<label for="sleep-cbox">睡觉</label>
</p>
<h3>{{ isChecked }}</h3>
data() {
return {
isChecked: false
}
}
等价于
<p>
<input type="checkbox" id="sleep-cbox" :checked="isChecked" @input="onCheck">
<label for="sleep-cbox">睡觉</label>
</p>
<h3>{{ isChecked }}</h3>
data() {
return {
isChecked: false
}
},
methods: {
onCheck(event) {
this.isChecked = event.target.checked;
}
}
再来一个清单应用案例:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
[v-cloak] {
display: none;
}
.done {
color: gray;
text-decoration: line-through;
}
</style>
</head>
<body>
<div id="app" v-cloak>
<!-- <h2>{{ title }}</h2> -->
<input type="text" v-model="title" @keydown.enter="addTodo">
<button v-if="active < all" @click="clear">清理</button>
<div v-if="todos.length">
<ul>
<li v-for="todo in todos">
<!-- <input :id="todo.title" type="checkbox" :checked="todo.done" @input="done"> -->
<input :id="todo.title" type="checkbox" v-model="todo.done">
<label :for="todo.title" :class="{ done: todo.done }">{{ todo.title }}</label>
</li>
</ul>
<!-- <div>{{ todos.filter(v => !v.done).length }} / {{ todos.length }}</div> -->
<div>
<label for="all-check">
全选<input type="checkbox" id="all-check" v-model="allDone">
</label>
<span>{{ active }} / {{ all }}</span>
</div>
</div>
<div v-else>暂无数据</div>
</div>
<script src="https://unpkg.com/vue@next"></script>
<script>
const App = {
data() {
return {
title: '',
// todos: ['学习 Vue', '跑步']
todos: [
{ title: '吃饭', done: true },
{ title: '学习', done: false },
{ title: '跑步', done: false }
]
}
},
computed: {
active() {
return this.todos.filter(v => !v.done).length;
},
all() {
return this.todos.length;
},
allDone: {
get() {
return this.active === 0;
},
set(val) {
this.todos.forEach(todo => todo.done = val);
}
}
},
methods: {
addTodo() {
// this.todos.push(this.title);
this.todos.push({ title: this.title, done: false });
this.title = '';
},
done(event) {
const target = this.todos.find(todo => todo.title === event.target.id);
target.done = event.target.checked;
},
clear() {
this.todos = this.todos.filter(todo => !todo.done);
}
}
};
// 启动应用
Vue.createApp(App).mount('#app');
</script>
</body>
</html>
效果展示:
1.3 绑定 type="radio" 的 <input> 元素
使用 type="radio" 的 <input> 元素时,通常会使用两个,这两个 <input> 元素上的 v-model 的值也是绑定到同一个属性,而它们的 value 属性值也应该是“互斥”的。选中这两个 <input> 元素中的一个时,另一个就会变为不选中,此时,选中的那个 <input> 元素的 value 就会自动绑定到对应的属性中:
<span>性别:</span>
<label for="male">
<input id="male" type="radio" v-model="gender" value="male"> 男
</label>
<label for="female">
<input id="female" type="radio" v-model="gender" value="female"> 女
</label>
<h2>gender: {{ gender }}</h2>
data() {
return {
gender: 'male'
}
}
1.4 绑定 <select> 元素
<select> 元素可以设置为单选,也可以设置为多选,但单选相对来说更常见。<select> 元素中会有多个 <option> 元素,每个 <option> 元素上的 value 属性应该设置对应的值,一旦选中某个 <option>,就会将它上面对应的 value 属性值绑定到 v-model 对应的属性里面:
<span>喜欢的水果:</span>
<select v-model="fruits">
<!-- <select v-model="fruits" multiple size="2"> -->
<option value="apple">苹果</option>
<option value="banana">香蕉</option>
<option value="peach">桃子</option>
</select>
<h2>fruits: {{ fruits }}</h2>
data() {
return {
fruits: 'apple'
}
}
以上关于 v-model 绑定其它表单元素的案例完整代码如下(<body> 元素中的代码):
<div id="app"></div>
<template id="my-app">
<!-- 1. 绑定 textarea -->
<label for="introduction">
自我介绍:
<textarea id="introduction" v-model="intro" cols="30" rows="10"></textarea>
</label>
<h2>intro: {{ intro }}</h2>
<!-- 2. 绑定 type="checkbox" 的 input -->
<!-- 2.1 单选框 -->
<label for="agreement">
<input id="agreement" type="checkbox" v-model="isAgree"> 同意协议
</label>
<h2>isAgree: {{ isAgree }}</h2>
<!-- 2.2 多选框 -->
<span>爱好:</span>
<label for="basketball">
<input id="basketball" type="checkbox" v-model="hobbies" value="basketball"> 篮球
</label>
<label for="football">
<input id="football" type="checkbox" v-model="hobbies" value="football"> 足球
</label>
<label for="volleyball">
<input id="volleyball" type="checkbox" v-model="hobbies" value="volleyball"> 排球
</label>
<h2>hobbies: {{ hobbies }}</h2>
<!-- 3. 绑定 type="radio" 的 input -->
<span>性别:</span>
<label for="male">
<input id="male" type="radio" v-model="gender" value="male"> 男
</label>
<label for="female">
<input id="female" type="radio" v-model="gender" value="female"> 女
</label>
<h2>gender: {{ gender }}</h2>
<!-- 4. 绑定 select -->
<span>喜欢的水果:</span>
<select v-model="fruits">
<!-- <select v-model="fruits" multiple size="2"> -->
<option value="apple">苹果</option>
<option value="banana">香蕉</option>
<option value="peach">桃子</option>
</select>
<h2>fruits: {{ fruits }}</h2>
</template>
<script src="./js/vue.js"></script>
<script>
const App = {
data() {
return {
intro: 'Hello World',
isAgree: false,
hobbies: [],
gender: 'male',
fruits: 'apple'
}
},
template: '#my-app'
};
Vue.createApp(App).mount('#app');
</script>