Vue v-model
月光晒了很凉快 人气:01. 概述
v-model 是 Vue 提供的一个语法糖,它是 value 值和事件的结合体,它会根据不同的表单项,来选择执行不同的事件。它的作用是,通过和表单元素绑定,实现双向数据绑定,通过表单项可以更改数据。
另外,v-model
还可以用于各种不同类型的输入,<textarea>
、<select>
元素。它会根据所使用的元素自动使用对应的 DOM 属性和事件组合:
- 文本类型的
<input>
和<textarea>
元素会绑定value
property 并侦听input
事件; <input type="checkbox">
和<input type="radio">
会绑定checked
property 并侦听change
事件;<select>
会绑定value
property 并侦听change
事件
v-model 会忽略所有表单元素的 value、checked、selected 特性的初始值,而总是将 Vue 实例的数据作为数据来源,应该在 data 选项中声明初始值。
语法糖:这种语法对语言的功能并没有影响,但是更方便程序员使用
2. 使用方法
在没有使用v-model指令时,我们通过data数据控制表单项中的值,还是麻烦的,需要绑定属性和事件来完成。
<div id="app"> <div> <input type="text" :value="username" @input="setUsername"> </div> </div> <script> const vm = new Vue({ el: '#app', data: { username: '' }, methods: { setUsername(evt) { this.username = evt.target.value.trim() } } }) </script>
使用 v-model 指令实现上述效果:
<div id="app"> <div> <input type="text" v-model="username"> </div> </div> <script> const vm = new Vue({ el: '#app', data: { username: '' } }) </script>
3. 案例
3.1 用户登录
使用 v-model 指令,可以很轻松的获取表单中的数据,也可以很轻松地对数据进行修改。
<!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>vue学习使用</title> <script src="./js/vue.js"></script> </head> <body> <div id="app"> <div> <label> 账号: <input type="text" v-model="username"> </label> </div> <div> <label> 密码: <input type="text" v-model="password"> </label> </div> <div> <textarea v-model="intro"></textarea> </div> <div> <button @click="dologin">登录系统</button> </div> </div> <script> const vm = new Vue({ el: '#app', data: { username: '', password: '', intro: 'hahaha' }, methods: { dologin() { console.log(this.username, this.password, this.intro); } } }) </script> </body> </html>
注意:多行文本框中使用插值表达式 无效
3.2 todolist
<!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>vue学习使用</title> <script src="./js/vue.js"></script> </head> <body> <div id="app"> <input placeholder="请输入内容" type="text" v-model="title" @keyup.enter="onEnter"> <hr> <ul> <!-- 条件渲染 --> <li v-if="todos.length===0">无任务</li> <li v-else v-for="item,index in todos" :key="item.id"> <span>{{item.title}}</span> <span @click="del(index)">删除</span> </li> </ul> </div> <script> const vm = new Vue({ el: '#app', data: { todos: [], title: '' }, methods: { onEnter() { this.todos.push({ id: Date.now(), title: this.title }) this.title = '' }, del(index) { // 删除 它可以使用 vue中提供的变异方法splice来完成,用此方法它会触发视图更新 this.todos.splice(index, 1) } } }) </script> </body> </html>
3.3 实现单个复选框
当单个复选框被选中或者被取消选中时,我们如何获取到该复选框是否被选中的信息?
我们可以通过绑定事件来获取:
<!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>vue学习使用</title> <!-- 第1步: 引入vue库文件 --> <script src="./js/vue.js"></script> </head> <body> <!-- 第2步:挂载点 --> <div id="app"> <div> <!-- click事件可以用,但它是的状态会太过提前,用onchange事件,改变后来获取 --> <input type="checkbox" @click="clickFn"> <input type="checkbox" @change="clickFn"> </div> </div> <!-- 第3步:实例化vue --> <script> const vm = new Vue({ el: '#app', data: { // 单个复选框一定要用布尔类型 checked: false }, methods: { clickFn(evt) { console.log(evt.target.checked); } } }) </script> </body> </html>
注意:在绑定事件时,click事件可以用,但它是的状态会太过提前,所以用onchange事件,改变后再来获取。
更简单的方式是,通过 v-model 指令来获取:
<!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>vue学习使用</title> <!-- 第1步: 引入vue库文件 --> <script src="./js/vue.js"></script> </head> <body> <!-- 第2步:挂载点 --> <div id="app"> <div> <!-- 单个复选框,在数据源中定义的数据类型为布尔类型 true选中,false未选中 --> <input type="checkbox" v-model="checked"> </div> </div> <!-- 第3步:实例化vue --> <script> const vm = new Vue({ el: '#app', data: { // 单个复选框一定要用布尔类型 checked: false }, methods: { } }) </script> </body> </html>
注意:单个复选框,在数据源中定义的数据类型为布尔类型:true 选中,false未选中
3.4 实现多个复选框
<!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>vue学习使用</title> <!-- 第1步: 引入vue库文件 --> <script src="./js/vue.js"></script> </head> <body> <!-- 第2步:挂载点 --> <div id="app"> <div> <!-- --> <ul> <li> <input type="checkbox" value="html" v-model="lessons">html </li> <li> <input type="checkbox" value="css" v-model="lessons">css </li> <li> <input type="checkbox" value="js" v-model="lessons">js </li> </ul> <hr> <div>{{lessons}}</div> </div> </div> <!-- 第3步:实例化vue --> <script> const vm = new Vue({ el: '#app', data: { // 默认选中 lessons: ["js",'css'] }, methods: { } }) </script> </body> </html>
注意:多个复选框,数据源中定义的数据类型为数组,标签中需要指定它的value值。
3.5 实现复选框全选
<!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>vue学习使用</title> <!-- 第1步: 引入vue库文件 --> <script src="./js/vue.js"></script> </head> <body> <!-- 第2步:挂载点 --> <div id="app"> <div> <input type="checkbox" v-model="checked" @change="onSelected"> <hr> <ul> <li> <input type="checkbox" value="html" @change="selectlesson" v-model="lessons">html </li> <li> <input type="checkbox" value="css" @change="selectlesson" v-model="lessons">css </li> <li> <input type="checkbox" value="js" @change="selectlesson" v-model="lessons">js </li> </ul> <hr> <div>{{lessons}}</div> </div> </div> <!-- 第3步:实例化vue --> <script> const vm = new Vue({ el: '#app', data: { lessons: [], checked: false }, methods: { onSelected(evt) { // 选中了 if (evt.target.checked) { this.lessons = ["js", 'html', 'css'] } else { this.lessons = [] } }, selectlesson() { // 只要来操作数据源就可以改变视图 this.checked = this.lessons.length == 3 } } }) </script> </body> </html>
3.6 单选和下拉
<!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>vue学习使用</title> <!-- 第1步: 引入vue库文件 --> <script src="./js/vue.js"></script> </head> <body> <!-- 第2步:挂载点 --> <div id="app"> <div> <h3>{{sex}} -- {{city}}</h3> <!-- 定义的数据类型为字符串 --> <label> <input type="radio" value="先生" v-model="sex">建行 </label> <label> <input type="radio" value="女神" v-model="sex">招行 </label> </div> <hr> <div> <select v-model="city"> <option value="0">==选择==</option> <option value="wh">芜湖</option> <option value="bj">北京</option> </select> </div> </div> <!-- 第3步:实例化vue --> <script> const vm = new Vue({ el: '#app', data: { sex: '先生', city: '0' } }) </script> </body> </html>
注意:单选框和复选框都需要 input 标签提供 value 属性。
4. v-model修饰符
4.1 lazy
作用:延时更新数据源中的数据,失去焦点时触发更新。
<div id="app"> <!-- v-model修饰符 --> <!-- 延时更新数据源中的数据 光标移开才会改变数据 --> <input v-model.lazy="title"> </div> <script> const vm = new Vue({ el: '#app', data: { title: '' } }) </script>
4.2 trim
作用:自动过滤用户输入的首尾空白字符。
<div id="app"> <!-- 去空格 trim --> <input v-model.trim="title"> </div> <script> const vm = new Vue({ el: '#app', data: { title: '' } }) </script>
4.3 number
作用:输入值转为数值类型。
<div id="app"> <!-- 转为数值 number --> <input type="number" v-model.number="n1"> + <input type="number" v-model.number="n2"> = {{n1+n2}} </div> <script> const vm = new Vue({ el: '#app', data: { n1: 1, n2: 2 } }) </script>
5. 案例
5.1 购物车
<!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>vue学习使用</title> <!-- 第1步: 引入vue库文件 --> <script src="./js/vue.js"></script> </head> <body> <!-- 第2步:挂载点 --> <div id="app"> <table border="1" width="600"> <tr> <th>序号</th> <th>名称</th> <th>单价</th> <th>数量</th> <th>操作</th> </tr> <tr v-for="item,index in carts"> <td>{{index+1}}</td> <td>{{item.name}}</td> <td>{{item.price}}</td> <td> <button @click="setNum(1,index)">+++</button> <input type="number" v-model="item.num"> <button @click="setNum(-1,index)">---</button> </td> <td> <button @click="del(index)">删除</button> </td> </tr> </table> <hr> <h3> 合计: {{totalPrice()}} </h3> </div> <!-- 第3步:实例化vue --> <script> const vm = new Vue({ el: '#app', data: { carts: [ { id: 1, name: '小米12pro', price: 1, num: 1 }, { id: 2, name: '华为手机', price: 2, num: 1 }, { id: 3, name: '水果手机', price: 3, num: 1 }, ] }, methods: { setNum(n, index) { this.carts[index].num += n if (this.carts[index].num <= 1) this.carts[index].num = 1 if (this.carts[index].num >= 3) this.carts[index].num = 3 // 用最大值和最小值来限制它的范围,可以了解一下这种写法 // this.carts[index].num = Math.min(3, Math.max(1, this.carts[index].num)) }, totalPrice() { // 聚合运算 return this.carts.reduce((prev, { price, num }) => { prev += price * num return prev }, 0) }, del(index) { // 弹出确认框 confirm('确定删除') && this.carts.splice(index, 1) } } }) </script> </body> </html>
5.2 购物车持久化
<!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>vue学习使用</title> <!-- 第1步: 引入vue库文件 --> <script src="./js/vue.js"></script> </head> <body> <!-- 第2步:挂载点 --> <div id="app"> <table border="1" width="600"> <tr> <th>序号</th> <th>名称</th> <th>单价</th> <th>数量</th> <th>操作</th> </tr> <tr v-for="item,index in carts"> <td>{{index+1}}</td> <td>{{item.name}}</td> <td>{{item.price}}</td> <td> <button @click="setNum(1,index)">+++</button> <input type="number" v-model="item.num"> <!-- <button @click="setNum(-1,item)">---</button> --> <button @click="setNum(-1,index)">---</button> </td> <td> <button @click="del(index)">删除</button> </td> </tr> </table> <hr> <h3> 合计: {{totalPrice()}} </h3> </div> <!-- 第3步:实例化vue --> <script> // 初始数据应该从本地存储中读取 function getCarts() { return !window.localStorage.getItem('carts') ? [{ id: 1, name: '小米12pro', price: 1, num: 1 }, { id: 2, name: '华为手机', price: 2, num: 1 }, { id: 3, name: '水果手机', price: 3, num: 1 }] : JSON.parse(window.localStorage.getItem('carts')) } function setCarts(carts) { window.localStorage.setItem('carts', JSON.stringify(carts)) } const vm = new Vue({ el: '#app', data: { carts: getCarts() }, methods: { setNum(n, index) { this.carts[index].num += n if (this.carts[index].num <= 1) this.carts[index].num = 1 if (this.carts[index].num >= 3) this.carts[index].num = 3 // 用最大值和最小值来限制它的范围,可以了解一下 // this.carts[index].num = Math.min(3, Math.max(1, this.carts[index].num)) setCarts(this.carts) }, totalPrice() { return this.carts.reduce((prev, { price, num }) => { prev += price * num return prev }, 0) }, del(index) { if(confirm('确定删除')){ this.carts.splice(index, 1) setCarts(this.carts) } } } }) </script> </body> </html>
加载全部内容