【Vue】基础系列(三三)指令语法-事件及其修饰符,动态样式,v-model的用法,数据持久化存在本地localStorage
和阿牛一起冲Vue
🌕写在前面
🍊博客主页 :勇敢link牛牛
🎉欢迎关注:🔎点赞👍收藏⭐️留言📝
🌟本文由 勇敢link牛牛 原创,CSDN首发!
📆首发时间:🌹2022年8月30日🌹
🆕最新更新时间:🎄2022年8月30日🎄
✉️愿你熬过万丈孤独,藏下星辰大海!
📠参考书籍:📚《Vue2》
🙏作者水平很有限,如果发现错误,请留言轰炸哦!万分感谢感谢感谢!
指令语法-事件及其修饰符,动态样式,数据持久化
- 和阿牛一起冲Vue
- 指令集合
- v-bind动态属性数据绑定
- 循环 v-for
- v-on事件及事件对象
- Todos案例;
- 事件修饰符
- 按键修饰符
- 动态绑定样式
- class样式处理
- 绑定style
- v-model指令,受控 input表单
- 单个,多个,全选框
- 单选和下拉
- v-model修饰符
- 购物车持久化
- 自定义指令-表单验证
指令集合
v-bind动态属性数据绑定
v-bind
动态属性数据绑定
语法:
- 标准语法:v-bind:属性=“动态数据”
- 简写语法::属性=“动态数据”
<div id="app">
<img src="http://www.mobiletrain.org/images_index/right-fixed-face.png" alt="">
<img v-bind:src="src" alt="">
<img :src="src" alt="">
</div>
<script>
const vm = new Vue({
el: '#app',
data: {
src: 'http://www.mobiletrain.org/images_index/right-fixed-face.png'
}
})
</script>
循环 v-for
vue中对于v-for进行了增强,它可以用
for in/of
都可以,而且两者都可以进行对象的迭代
语法:vue2中小括号可以写,也可以不写,在vue3中一定要写小括号
注:
- vue2中如果一个标签中同时有
v-if
和v-for
,则v-for的优先级高于v-if,所以在vue2中不推荐两者在一个标签中 - vue3中v-if优先级高于v-for
语法: v-for="(元素,索引) in/of 数组"
语法:v-for="(元素,键名,索引) in/of 对象"
注:v-for,建议给循环项每个添加一个key来作标识,用于提升性能,key值,一定要唯一不重复的,不太建议使用循环的索引当作key值,一般在和后台请求数据时,要求后台提供一个唯一的id给我们
<!-- 循环数组 -->
<li v-for="(item,index) in user">{{index}} -- {{item}}</li>
<li v-for="item,index in user">{{index}} -- {{item}}</li>
<li v-for="item,index in user" :key="item.id">{{item.name}}</li>
<!-- 循环对象 -->
<div v-for="item,key,index in user" :key="key">{{index}} -- {{key}} -- {{item}}</div>
v-on事件及事件对象
v-on:事件名="实现的方法[此方法定义在vue配置中的methods中]"
v-on使用很频繁,可以使用语法糖: @事件名=“方法”
绑定的方法,它可以写小括号,也可以不写小括号
** @click="change"事件**
<div id="app">
{{message}}
<button @click="change">点击改变信息</button>
<button v-on:click="clickFn">点击事件</button>
<button @click="clickFn">点击事件</button>
<button @click="($event)=>change($event)">点击改变信息</button>
</div>
methods中定义方法不用使用箭头函数,但是在方法体中建议使用箭头函数,用来保持this指向
var vm = new Vue({
el:"#app",
data:function(){
return {
message:"车到山前必有路"
}
},
methods:{
change(){
setTimeout(()=>{
this.message= "我一定会回来的";
},2000)
}
}
})
1、如果你绑定方法时,没有写小括号,则vue在解析时,会自动给你映射一个event给绑定方法
2、如果你绑定方法时,有写小括号,则需要手动把event对象传过去$event
,$event
可以传多个,但是建议只传一个,一般写在第1位或最后1位(占位)
3、 event可以用它来完成dom数据的获取
知识点:
一般的自定义属性获取:
evt.target.getAttribute('uname')
h5新增的属性数据写法可以这样获取:
evt.target.dataset.uname
@keyup=“onEnter”:键盘事件。
<div id="app">
{{message}}
<input type="text" name="" id="" @keyup="onEnter">
</div>
<script>
var vm = new Vue({
el: "#app",
data: function () {
return {
message: "车到山前必有路"
}
},
methods: {
change() {
setTimeout(() => {
this.message = "我一定会回来的";
}, 2000)
},
onEnter(e) {
if(e.keyCode == 13){/* 键盘事件的key码 */
console.log(e.target.value);
this.message = e.target.value;
}
}
}
})
</script>
Todos案例;
<!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>todolist</title>
<script src="./vue.js"></script>
</head>
<body>
<div id="app">
<input type="text" placeholder="请输入内容" @keyup="onEnter">
<hr>
<ul>
<li v-if="todos.length == 0">无任务</li>
<li v-else v-for="(item,index) in todos" :key="item.id">
<span>{{item.id}}--{{item.message}}</span>
<button @click="onClick(index)">删除</button>
</li>
</ul>
</div>
<script>
var vm = new Vue({
el: "#app",
data: function () {
return {
todos: [{
id: Date.now(),
message: "我爱你"
}]
}
},
methods: {
onClick(index) {/* 可以使用 vue中提供的变异方法splice来完成,用此方法它会触发视图更新 */
this.todos.splice(index, 1)
},
del(id) {/* 通过id来删除数据 */
this.todos = this.todos.filter(item => item.id != id)
},
onEnter(e) {
if (e.keyCode == 13) {
/* 键盘事件的key码 */
this.todos.push({
id: Date.now(),
message: e.target.value
}); /* 变异方法,改变引起试图响应 */
e.target.value = '' /* 清空 */
}
}
}
})
</script>
</body>
</html>
事件修饰符
用来处理事件的特定行为
<!-- 阻止冒泡 -->
<button @click.stop="doThis"></button>
<!-- 阻止默认行为 -->
<a @click.prevent="doThis"></a>
<!-- 只执行一次 -->
<div @click.once="incr()">自增一下</div>
<!-- 绑定的元素本身触发时才触发回调 -->
<ul @click.self="incr()">
<li>你好世界</li>
</ul>
<!-- 串联修饰符 -->
<button @click.stop.prevent="doThis"></button>
按键修饰符
在监听键盘事件时,我们经常需要检查详细的按键。Vue 允许为 v-on 在监听键盘事件时添加按键修饰符。
<div id="app">
<!-- 只有在 `key` 是 `Enter` 回车键的时候调用 -->
<input placeholder="请输入内容" type="text" @keyup.alt.112="onEnter" >
</div>
<!-- Ctrl + Click -->
<div @click.ctrl="doSomething">Do something</div>
你还可以通过全局 config.keyCodes 对象自定义按键修饰符别名:
// 可以使用 `v-on:keyup.f1`
Vue.config.keyCodes = {f2:113}
<input @keyup.f2="add()" value="aaaa">
动态绑定样式
class样式处理
class样式的动态添加,有这个对象和数组两种方式
- 对象:
{key它就是样式名称:布尔值【true生效,false不生效】}
- 一般用于开关显示的样式,不太适合添加新的属性样式
- 但是问题是这样只针对初始化时对象里面的布尔值做修改会让试图更新
- 只能做当前数据的更改视图才会更新,后来的不更新。
- 那么就有了新的一个方法:
this.$set(this.titleClass, 'font30', true)
- 动态给对象添加成员属性;
- 以下是多种触发方式
- 那么就有了新的一个方法:
this.titleClass = Object.assign({}, this.titleClass, { font30: true }
let titleClass = JSON.parse(JSON.stringify(this.titleClass))
titleClass.font30 = true
this.titleClass = titleClass
let obj = Object.assign(参数1地址和返回值地址是同一个地址)
- 数组:
[元素样式名称]
- 一般对于追加新样式,使用数组
- 给数组添加元素,元素就是样式名称,这样它会就追加样式
- push unshift shift pop splice sort reverse 调用时都会让视图更新
<head>
<script src="./js/vue.js"></script>
<style>
.active {
color: red;
}
.font30 {
font-size: 30px;
}
</style>
</head>
<body>
<div id="app">
<div :class="titleStyle">我是一个标题</div>
<button @click="addStyle">添加样式</button>
</div>
<script>
const vm = new Vue({
el: '#app',
data: {
titleClass: {
active: false
},
titleStyle: []
},
methods: {
addClass() {
// 动态给对象添加成员属性
this.$set(this.titleClass, 'font30', true)
// this.titleClass.active = !this.titleClass.active
// this.titleClass.active = true
// this.titleClass = { ...this.titleClass, font30: true }
// let titleClass = JSON.parse(JSON.stringify(this.titleClass))
// titleClass.font30 = true
// this.titleClass = titleClass
// this.titleClass = Object.assign({}, this.titleClass, { font30: true })
// let obj = Object.assign(参数1地址和返回值地址是同一个地址)
},
addStyle() {
// 给数组添加元素,元素就是样式名称,这样它会就追加样式
// push unshift shift pop splice sort reverse 调用时都会让视图更新
this.titleStyle.push('active')
this.titleStyle.push('font30')
}
}
})
</script>
</body>
</html>
绑定style
style样式的动态添加,对象和数组方式
和绑定calss类一样
对象
<div :style="{color:'blue',fontSize:'30px'}">我是一个标题</div>
数组
<div :style="[{color:'blue'},{fontSize:'30px'}]">我是一个标题</div>
v-model指令,受控 input表单
在没有使用v-model指令时,来通过data数据控制表单项中的值,还是麻烦滴
需要绑定属性和事件来完成 -- 受控组件
<input type="text" :value="username" @input="setUsername">
v-model它是一个语法糖,value和事件的综合体
<input type="text" v-model="username">
虽然是双向数据绑定,但是uesrname的数据优先级高于input本身,因为在触发input.value=''
之后他是不会生效的,而uesrname值清空的话就会清空。
TODOs案例:
<body>
<div id="app">
<input type="text" placeholder="请输入内容" v-model="message" @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.id}}--{{item.message}}</span>
<button @click="onClick(index)">删除</button>
</li>
</ul>
</div>
<script>
var vm = new Vue({
el: "#app",
data: function () {
return {
todos: [],
message:'',
}
},
methods: {
onClick(index) {/* 可以使用 vue中提供的变异方法splice来完成,用此方法它会触发视图更新 */
this.todos.splice(index, 1)
}
onEnter(e) {
this.todos.push({
id: Date.now(),
message:this.message
}); /* 变异方法,改变引起视图更新 */
this.message =''
}
}
})
</script>
</body>
单个,多个,全选框
v-model:单个:布尔值
单个复选框,定义的数据类型为布尔类型 true选中,false未选中
单个复选框一定要用布尔类型
<input type="checkbox" v-model="checked">
click事件可以用,但它是的状态有太过提前,用onchange事件,改变后来获取
<input type="checkbox" @click="clickFn">
<input type="checkbox" @change="clickFn">
v-model:多个:数组类型绑定,必须加value
<body>
<div id="app">
<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>
<script>
const vm = new Vue({
el: '#app',
data: {
lessons: ["js"]
},
methods: {}
})
</script>
</body>
全选案例;
<body>
<div id="app">
<label for="">全选<input type="checkbox" @change="onChange" v-model="checked"></label>
<hr>
<ul>
<li>
<input type="checkbox" value="html" v-model="lessons" @change="seeions">html
</li>
<li>
<input type="checkbox" value="css" v-model="lessons" @change="seeions">css
</li>
<li>
<input type="checkbox" value="js" v-model="lessons" @change="seeions">js
</li>
</ul>
<hr>
<div>{{lessons}}</div>
</div>
</div>
<script>
const vm = new Vue({
el: '#app',
data: {
lessons: ["js"],
checked:false
},
methods: {
onChange(){
if(this.checked){
this.lessons = ["js","css","html"]
}else{
this.lessons = []
}
},
seeions(){
if(this.lessons.length == 3) this.checked = true;
else this.checked = false;
}
}
})
</script>
</body>
单选和下拉
单选:定义的数据类型为字符串,也必须要value属性。
下拉:字符串,value初始化绑定。
<body>
<div id="app">
<h1>{{sex}}-{{city}}</h1>
<label for=""><input type="radio" value="男士" v-model="sex">男士</label>
<label for=""><input type="radio" value="女士" v-model="sex">女士</label>
<hr>
<select name="" id="" v-model="city">
<option value="上海">上海</option>
<option value="天津">天津</option>
<option value="起飞">起飞</option>
<option value="北京">北京</option>
</select>
</div>
<script>
const vm = new Vue({
el: '#app',
data: {
sex:"男士",
city:"北京"
},
methods: {
}
})
</script>
</body>
v-model修饰符
延迟更新,去空格,转为数组
延时更新数据源中的数据
<input v-model.lazy="title">
去空格 trim
<input v-model.trim="title">
转为数值 number
<input type="number" v-model.number="m">+<input type="number" v-model.number="n">={{m+n}}
购物车持久化
非持久化:
<!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>
<script src="./vue.js"></script>
<style>
tr,td{
text-align: center;
}
</style>
</head>
<body>
<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 product">
<td>{{index+1}}</td>
<td>{{item.name}}</td>
<td>{{item.price}}</td>
<td><button @click="change(1,index)">+</button><input v-model="item.num"><button @click="change(-1,index)">-</button></td>
<td><button @click="del(index)">删除</button></td>
</tr>
</table>
<hr>
<h3>
合计:
{{totalPrice()}}
</h3>
</div>
<script>
new Vue({
el:"#app",
data:function(){
return {
product:[{ id: 1, name: '小米12pro', price: 1, num: 1 }, { id: 2, name: '华为手机', price: 2, num: 1 },{ id: 3, name: '水果手机', price: 3, num: 1 }]
}
},
methods:{
totalPrice(){
return this.product.reduce((v,{price,num})=>v += price*num,0);/* 解构 */
},
change(n,index){
this.product[index].num += n
},
del(index){
this.product.splice(index,1);
}
}
})
</script>
</body>
</html>
持久化数据:
<head>
<script src="./vue.js"></script>
<style>
tr,td{
text-align: center;
}
</style>
</head>
<body>
<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 product">
<td>{{index+1}}</td>
<td>{{item.name}}</td>
<td>{{item.price}}</td>
<td><button @click="change(1,index)">+</button><input v-model="item.num"><button @click="change(-1,index)">-</button></td>
<td><button @click="del(index)">删除</button></td>
</tr>
</table>
<hr>
<h3>
合计:
{{totalPrice()}}
</h3>
</div>
<script>
function getData(){
return !window.localStorage.getItem("product") ?[{ 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("product"))
}
function setData(product){
localStorage.setItem("product",JSON.stringify(product))
}
new Vue({
el:"#app",
data:function(){
return {
product: getData(),
}
},
methods:{
totalPrice(){
return this.product.reduce((v,{price,num})=>v += price*num,0);/* 解构 */
},
change(n,index){
this.product[index].num += n
},
del(index){
this.product.splice(index,1);
setData(this.product)
}
}
})
</script>
</body>
</html>
自定义指令-表单验证
全局定义,所有的组件或vue的实例都会生效,可以使用。
对象写法,它提供5个钩子(插口)函数:也是它的生命周期
语法:Vue.directive('指令名称,不需要写v-开头',对象或函数)
注意单词的拼写:
Vue.directive('red', {
// bind 第一次绑定到元素时调用
bind(el, bindings) {
console.log('bind')
el.style.cssText = `color:red;font-size:30px`
},
// inserted
inserted(el, bindings) {
console.log('inserted');
},
// update
update(el, bindings) {
console.log('update');
},
// componentUpdate
componentUpdated(el, bindings) {
console.log('componentUpdated');
},
// unbind
unbind(el, bindings) {
console.log('unbind');
},