移动端开发之一vue指令和事件处理
任务目标
-
了解什么是 Vue.js 指令
-
理解 Vue.js 指令的用途
-
掌握 Vue.js 指令的书写规范
-
能够使用 Vue.js 指令完成部分页面交互效果
一、vue指令
1.1 相关插件安装
高亮代码括号的插件
vue的代码提示插件
标签重命名插件
1.2 什么是 Vue指令
指令 (Directives) 是带有 v-
前缀的特殊 attribute。指令 attribute 的值预期是单个 JavaScript 表达式。指令的职责是,当表达式的值改变时,将其产生的连带影响,响应式地作用于 DOM。解析模板/标签(标签属性,标签体内容,绑定事件等) 例如:
//点击toggle按钮,会显示红色方块,再次点击,红色方块消失,这里就是通过控制属性的真假,通过指令作用到红色方块上来控制方块的显示隐藏
<button v-on:click="isaaa = !isaaa">toggle</button>
<div class="block" v-show="isaaa"></div>
1.3 Vue.js 指令的书写规范
//书写位置:任意 HTML 元素的开始标签内
<p v-if="seen">现在你看到我了</p>
//注意:一个开始标签内可写入多个指令,多个指令间使用空格分隔
<a href="javascript:;" :class="{active:timeflag}" @click="queryAll('time')">全部</a>
1.4 常用指令
-
v-text
语法格式:
v-text='表达式'
作用相当于之前学习的DOM操作中的innerText属性,会直接覆盖元素中原本的文本内容,实际开发中使用不多
<p v-text="name+'法撒旦'"></p> <script> let app = new Vue({ el:'p', data:{ stat:true, name:'张三' } }) </script>
-
v-html
语法格式:
v-html='表达式'
作用相当于DOM操作中的innerHTML属性,可以识别字符串中的标签。
<p v-html="msg"></p> <script> let app = new Vue({ el:'p', data:{ msg:'<h1>你好哈哈哈</h1>' } }) </script>
-
v-if
v-else-if
v-else
作用等同于js代码中的 if else if elseif else 帮助我们按照需求去控制DOM元素的显示与隐藏。
语法格式:
v-if='表达式'
v-else-if='表达式'
v-else='表达式'
注意: v-if 和后续的v-else-if v-else都要连续使用,如果中间有间隔,效果是可以正常显示的,但是,控制台会报错。这个特性针对操作同级元素的时候来说。
<body> <div id="max"> <ul v-if='num>10'> <li>你好哈哈1</li> <li>你好哈哈2</li> <li>你好哈哈3</li> </ul> <ul v-else="num>5"> <li>你好嘿嘿1</li> <li>你好嘿嘿2</li> <li>你好嘿嘿3</li> </ul> </div> </body> <script> let app = new Vue({ el: '#max', data: { num: 9 } }) </script>
-
v-show
控制元素是否显示,作用等同于css样式的display:none 或非none
语法格式:
v-show='true/false'
; true为显示,false为不显示<div id="max"> <p v-show='stat'>你好哈哈哈</p> <button v-on:click='tiggleShow()'>点我</button> </div> <script type="text/javascript"> let app = new Vue({ el:'#max', data:{ stat:true, }, methods:{ tiggleShow(){ this.stat = !this.stat; } } }) </script>
v-if与v-show区别: v-show指令的元素始终会被渲染到HTML 它只是简单地为元素设置CSS的style属性。当不满足条件的元素被设置style="display:none"样式 v-if指令满足条件是,会渲染到html中,不满足条件时,是不会渲染到html中的 v-if 指令有更高的切换消耗 v-if当条件成立的时候会将元素加上,不成立的时候,就会移除dom,并且内部的指令不会执行 v-show 指令有更高的初始渲染消耗 v-show只是简单的隐藏和显示 如果需要频繁切换使用 v‐show 较好,如果在运行时条件不大可能改变 使用v‐if 较好
-
v-for
循环遍历 #*v-for的作用等同于js代码中的for循环,用于循环生成DOM结构,想循环哪个DOM结构,就在哪个DOM结构上添加v-for。
但凡使用到v-for的地方 必须添加第二个属性 :key='id'
<body> <div id="box"> <!-- 遍历数组 语法 v-for="(item,index) in arr" item 就表示数组中的每一个数据 index表示下标 --> <ul> <li v-for="(item,index) in arr">{{item}}</li> </ul> <!-- 遍历普通对象 语法 v-for="(val,key,i) in arr" val 就表示对象中的每一个值 key 就表示对象中的每一个键值 i就是下标 --> <ul> <li v-for="(val,key,i) in user">{{key}}--{{val}}--{{i}}</li> </ul> <!-- 遍历字符串 --> <ul> <li v-for="(item,i) in str">{{item}}</li> </ul> </div> <script> let app = new Vue({ el: '#box', data: { arr: ['a', 'b', 'c'], user: { "name": '张三', "age": 18, "address": '郑州' }, str:'abcdefg' } }) </script> </body>
-
v-on
绑定事件和事件处理vue的绑定事件的方式,只需要把原生事件名字的on去掉就可以了
例如: onclick = > @click/v-on:click onblur => @blur/v-on:blur
-
普通用法
为 HTML 元素绑定事件监听 v-on:事件名称 =‘函数名称()’ 表达式可以是一个方法的名字或一个内联语句 简写语法:@事件名称 =‘函数名称()’ 注意:函数定义在 methods 配置项中 <button v-on:click='fn()'>toggle</button> v-on: 可以简写成 @ <button @click='fn()'>toggle</button>
-
-
v-bind
作用:为元素的属性 动态的绑定值
v-bind可以在其名称后面带一个参数,参数通常是HTML元素的属性(attribute),v-bind是动态绑定指令,默认情况下自带属性的值是固定的,为了能够动态的给这些属性添加/修改值可以使用v-bind指令
v-bind:属性名 = ‘表达式’
简写形式:v-bind可以省略,直接书写为 :属性名 = ‘表达式’
<img v-bind:src="imageSrc"> 等价于 <img :src="imageSrc"> //绑定一个属性
v-bind:绑定class
//对象语法
我们可以传给 v-bind:class 一个对象,以动态地切换 class:
格式:<div v-bind:class="{ 类名: 布尔值 }"></div>
//isActive是boolean属性的参数,为true就给div添加类名active,为false就不添加
<div v-bind:class="{ active: isActive }"></div>
可以同时绑定多个类名,也可以和静态类名同时存在
<div class="static" v-bind:class="{ active: isActive, 'text-danger': hasError }"></div>
//数组语法
我们可以把一个数组传给 v-bind:class,以应用一个 class 列表:
<div v-bind:class="[activeClass, errorClass]"></div>
data: {
activeClass: 'active',
errorClass: 'text-danger'
}
<div v-bind:class="[isActive ? activeClass : '', errorClass]"></div>
//绑定多个属性
<div v-bind:class="{'textColor':isColor, 'textSize':isSize}">多个样式的绑定</div>
<div id="box">
<a :href="url" v-bind:class='classname'>点我</a>
</div>
<script>
new Vue({
el:'#box',
data:{
url:'http://www.baidu.com',
classname:['aaa','bbb','ccc']
}
})
</script>
v-bind:绑定内联样式
#对象语法
//v-bind:style 的对象语法十分直观——看着非常像 CSS,但其实是一个 JavaScript 对象。CSS property 名可以用驼峰式 (camelCase) 或短横线分隔 (kebab-case,记得用引号括起来) 来命名:
<div v-bind:style="{ color: activeColor, fontSize: fontSize + 'px' }"></div>
data: {
activeColor: 'red',
fontSize: 30
}
//直接绑定到一个样式对象通常更好,这会让模板更清晰:
<div v-bind:style="styleObject"></div>
data: {
styleObject: {
color: 'red',
fontSize: '13px'
}
}
#数组语法
//v-bind:style 的数组语法可以将多个样式对象应用到同一个元素上:
<div v-bind:style="[styleObject,baseStyles, overridingStyles]"></div>
-
v-model
你可以用
v-model
指令在表单<input>
、<textarea>
及<select>
元素上创建双向数据绑定。它会根据控件类型自动选取正确的方法来更新元素。尽管有些神奇,但v-model
本质上不过是语法糖。它负责监听用户的输入事件以更新数据,并对一些极端场景进行一些特殊处理。v-model
会忽略所有表单元素的value
、checked
、selected
attribute 的初始值而总是将 Vue 实例的数据作为数据来源。你应该通过 JavaScript 在组件的data
选项中声明初始值。v-model说白了就像监听器一样,会自动的将vue实例的值同步更新到表单中,同样的也会把表达中的值同步到vue实例中。
这就是双向数据绑定。
注意:只有表单元素使用v-model使用才有意义,因为只有表单元素才可以跟用户交互。别的元素使用只能显示数据,没有别的意义。
对input框,操作的是value属性的值:
<body> <div class="box"> <input type="text" value="你好嘿嘿嘿" v-model='msg'> <br> {{msg}} </div> <script> new Vue({ el:'.box', data:{ msg:'你好哈哈哈' } }) </script> </body>
对单个复选框操作的是 checked属性的值:
<body> <div class="box"> <input type="checkbox" v-model='b'> <br> {{b}} </div> <script> new Vue({ el:'.box', data:{ b:'' } }) </script> </body> 此时vue实例中b的值会就跟复选框绑定到了一起。
对多个复选框操作如果在vue实例中是用一个数组接收,接收到是一个数组,里边包含的是被选中的复选框的vlaue值
<body> <div class="box"> <input type="checkbox" value="1" v-model='b'> <input type="checkbox" value="2" v-model='b'> <input type="checkbox" value="3" v-model='b'> <br> {{b}} </div> <script> new Vue({ el:'.box', data:{ b:[] } }) </script> 想让哪个框默认选中,就直接把这个框的值写入到vue的实例中去。
对于单选框来说,拿到的是被选中的那个单选框的value属性的值:
<body> <div class="box"> <input type="radio" value="男" name="sex" v-model="s">男 <input type="radio" value="女" name="sex" v-model="s">女 <br> {{s}} </div> <script> new Vue({ el:'.box', data:{ s:"" } }) </script> </body>
对于下拉框来说,拿到的是被选中的那个选项的值
<body> <div class="box"> <select name="" id="" v-model="selected" multiple> <option value="a">a</option> <option value="b">b</option> <option value="c">c</option> <option value="d">d</option> </select> <br> {{selected}} </div> <script> new Vue({ el:'.box', data:{ selected:'' } }) </script> </body> 此时selected拿到的就是被选中的项的value值,如果是多选的下拉框,此时的selected值就是选中的多个框的value值。
-
v-model的专用修饰符
.lazy - 取代 input 监听 change 事件 原本的数据绑定相当于对input框进行oninput事件监听,使用v-model.lazy之后相当于把oninput事件换成了onchange事件 .number - 输入字符串转为有效的数字 自动转换为数字 <div id="app"> <input type="text" v-model.number='num1'>+<input type="text" v-model.number='num2'>=<span>{{num1+num2}}</span> </div> <script> new Vue({ el:'#app', data:{ num1:1, num2:2 } }) </script> .trim - 输入首尾空格过滤
1.5 事件处理
-
vue中的event事件对象:
如果调用函数时不传递参数,那么在函数中可以直接使用e来表示事件对象,但是如果进行参数的传递,在函数内部就无法再使用e了,此时 vue中给我们提供了一个 $event 来表示时间对象,只需要调用函数时传入即可。
获取事件对象
<div id="max">
<button @click='fn($event)'>点我获取事件对象</button>
</div>
<script>
new Vue({
el: '#max',
methods: {
fn(e){
console.log(e);
}
}
})
</script>
-
事件修饰符
v-on后面可以增加修饰符 <div @click.stop='fn()'>点我</div> 事件修饰符: 常用: .stop:调用event.stopPropagation() 阻止事件冒泡 .prevent : 调用event.preventDefault()阻止默认行为 不常用: .self : 只当事件是从侦听器绑定的元素本身触发时才触发回调 例如:如果不想添加冒泡事件,可以给父子级的元素都添加.self修饰符这样就不会触发冒泡事件,只有在点击元素自身的时候才会触发。 .once:点击事件将只会触发一次 事件只会被触发一次,触发后,底层就会解绑事件 类似于jquery中one()事件绑定 .capture:添加事件监听器时使用事件捕获模式 .passive:滚动事件的默认行为 (即滚动行为) 将会立即触发
-
按键修饰符
在监听键盘事件时,我们经常需要检查详细的按键。Vue 允许为
v-on
在监听键盘事件时添加按键修饰符:<!-- 只有在 `key` 是 `Enter` 时调用 `vm.submit()` --> <input v-on:keyup.enter="submit">
注意:
keyCode
的事件用法已经被废弃了并可能不会被最新的浏览器支持。使用
keyCode
attribute 也是允许的:<input v-on:keyup.13="fn1">enter键触发 <input v-on:keyup.65="fn2">a键触发
为了在必要的情况下支持旧浏览器,Vue 提供了绝大多数常用的按键码的别名:
-
.enter
-
.tab
-
.delete
(捕获“删除”和“退格”键) -
.esc
-
.space
-
.up
-
.down
-
.left
-
.right
有一些按键 (
.esc
以及所有的方向键) 在 IE9 中有不同的key
值, 如果你想支持 IE9,这些内置的别名应该是首选。你还可以通过全局
config.keyCodes
对象自定义按键修饰符别名:// 可以使用 `v-on:keyup.f1` <div id="max"> <input type="text" @keydown.aaa='fn4'> </div> <script> //单个定义 Vue.config.keyCodes.f1 = 112 //当以多个 Vue.config.keyCodes = { aaa:65, bbb:66 } new Vue({ el: '#max', methods: { fn4(){ alert('a键被按下了'); } } }) </script>
-
-
系统修饰键
系统修饰键 .ctrl .alt .shift .meta 注意:在 Mac 系统键盘上,meta 对应 command 键 (⌘)。在 Windows 系统键盘 meta 对应 Windows 徽标键 (⊞)。在 Sun 操作系统键盘上,meta 对应实心宝石键 (◆)。在其他特定键盘上,尤其在 MIT 和 Lisp 机器的键盘、以及其后继产品,比如 Knight 键盘、space-cadet 键盘,meta 被标记为“META”。在 Symbolics 键盘上,meta 被标记为“META”或者“Meta”。 <!-- Alt + C -->同时按下alt键和c键 <input v-on:keyup.alt.67="handler"> #请注意: 修饰键与常规按键不同,在和 keyup 事件一起用时,事件触发时修饰键必须处于按下状态。换句话说,只有在按住 ctrl 的情况下释放其它按键,才能触发 keyup.ctrl。而单单释放 ctrl 也不会触发事件。如果你想要这样的行为,请为 ctrl 换用 keyCode:keyup.17。
-
.exact
修饰符2.5.0 新增
.exact
修饰符允许你控制由精确的系统修饰符组合触发的事件。<!-- 只要按下的键中有ctrl键 事件就可以被触发 --> <button v-on:click.ctrl="onClick">A</button> <!-- 有且只有 Ctrl 被按下的时候才触发 --> <button v-on:click.ctrl.exact="onCtrlClick">A</button> <!-- 没有任何系统修饰符被按下的时候才触发 --> <button v-on:click.exact="onClick">A</button>
-
鼠标按钮修饰符
2.2.0 新增
-
.left
-
.right
-
.middle
这些修饰符会限制处理函数仅响应特定的鼠标按钮。
当点击鼠标右键时才会触发事件 <button @click.right='fn()'>鼠标修饰符</button>
-
二、案例作业
案例1—注册页面
需求说明 使用常见表单元素布局注册页面 使用v-model指令完成对应数据的绑定 填写的表单内容可以显示在表单下方
案例3—仿京东左侧菜单
需求说明 完成京东左侧菜单的页面布局 使用 v-for 指令遍历子分类名称,从而显示子分类的列表
案例4—导航切换
需求说明: 点击导航条中的导航项目,当前被点击的项目内容会显示在下方绿色方块中,并且当前被点击项目的背景会变成红色 使用 v-for 指令遍历显示导航项目,使用v-on添加添加事件,使用v-bind指令动态绑定class和key属性
案例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>Document</title>
<script src="./lib/vue.js"></script>
<style>
td{
height: 30px;
text-align: center;
}
</style>
</head>
<body>
<div id="app">
<div>
名称: <input type="text" v-model.trim="gName">
数量: <input type="text" v-model.number="gNum">
是否上架: <select v-model="gState">
<option value="true">上架</option>
<option value="false">下架</option>
</select>
<button @click="addGoods">新增商品</button>
</div>
<table border="1" width="800px">
<thead>
<th><input type="checkbox" @change="checkAll" v-model="allState"></th>
<th>编号</th>
<th>名称</th>
<th>状态</th>
<th>数量</th>
<th>操作</th>
</thead>
<tbody>
<tr v-for="(item,index) in goods">
<td><input type="checkbox" v-model="item.isChecked" @change="reverseChk"></td>
<td>{{item.id}}</td>
<td>{{item.name}}</td>
<td>
<span v-if="item.state">上架状态</span>
<span v-else>下架状态</span>
</td>
<td><button @click="add(item.id)">+</button><span>{{item.num}}</span><button @click="sub(item.id,index)">-</button></td>
<td>
<button @click="del($event,item.id)">删除</button>
<button v-if="item.state" @click="item.state=!item.state">点击下架</button>
<button v-else @click="item.state=!item.state">点击上架</button>
</td>
</tr>
</tbody>
</table>
<span>选中的商品的总数量:{{count}}</span>
</div>
<!-- <button onclick="alert()">点我</button> -->
</body>
<script>
/*
① 根据data数据渲染DOM结构
② 新增商品
③ 删除功能 根据id删除
④ 上下架功能 根据id修改上下架
⑤ 首先把数据中新增一个属性 isChecked
在把这个属性跟页面中的input框做双向数据绑定
全选:给全选框绑定事件
反选:给所有的复选框绑定事件
*/
new Vue({
el:'#app',
data:{
goods:[
{id:1,name:'苹果',state:true,num:5,isChecked:false},
{id:2,name:'香蕉',state:false,num:5,isChecked:false},
{id:3,name:'橘子',state:true,num:5,isChecked:true},
{id:4,name:'甘蔗',state:true,num:5,isChecked:false},
{id:5,name:'荔枝',state:true,num:5,isChecked:false}
],
//定义商品名称
gName:'',
//商品的数量
gNum:0,
//上下架的状态
gState:true,
//商品id
ids:5,
//全选状态
allState:false,
//记录选中的商品的总数量
//count:0
},
methods: {
//定义新增商品的方法/函数
addGoods(){
//1.先创建一个商品对象
let obj = {
id:++this.ids,
name:this.gName,
num:this.gNum,
state:this.gState
}
//2.把数据整体追加到 data中goods中
this.goods.push(obj);
},
//定义删除按钮
del(e,i){
//方式一:DOM方式 不推荐使用
//e.target.parentElement.parentElement.remove()
//e.target.parentNode.parentNode.remove()
//方式二:从数据的角度来删除
/* this.goods.forEach((item,index) => {
if(item.id==i){
//index表示删除的下标 1 表示删除的个数
this.goods.splice(index,1)
}
}); */
//使用数组的filter方法做过滤操作 拿到符合条件的所有结果
this.goods = this.goods.filter(item=>item.id!=i)
},
//定义修改状态的函数
/* changeState(i){
this.goods.forEach((item) => {
if(item.id==i){
//index表示删除的下标 1 表示删除的个数
item.state = !item.state
}
});
} */
//定义全选事件
checkAll(){
//全选:要把购物车中所有的选项的isChecked属性值都变成跟全选框一致
this.goods.forEach((item) => {
item.isChecked = this.allState
});
},
//定义反选事件
reverseChk(){
//点击每一个复选框时,都要对所有复选框做遍历,看里边是否存在isChecked为false的选项
//只要有false 那么allState也等于false
this.allState = this.goods.every(item=>item.isChecked==true)
},
//定义数量的增加方法
add(i){
this.goods.forEach((item) => {
if(item.id==i){
item.num+=1
}
});
},
//定义数量的减少方法
sub(i,a){
//如果数量为1的 就直接return
if(this.goods[a].num==1) return ;
this.goods.forEach((item) => {
if(item.id==i){
item.num-=1
}
});
}
},
computed: {
//计算选中结算的商品总数量
count(){
//先 筛选 出被选中的商品 再 计算中总数量赋值给count
return this.goods.filter(item=>item.isChecked==true).reduce((total,item)=>total+=item.num,0)
}
}
})
</script>
</html>
三、作业:
作业1:学生信息录入系统
作业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>Document</title>
<script src="../js/vue.js"></script>
<style>
.active{
text-decoration: line-through;
color: gray;
}
</style>
</head>
<body>
<div id="app">
<h1>任务列表</h1>
<h4>任务总数{{sum()}}; 未完成{{daiban()}};已完成{{sum()-daiban()}}</h4>
<ol>
<li v-for='(item,index) in lists'>
<input :id="item.id" v-model='item.isChecked' type="checkbox">
<span :class="{active:item.isChecked}" @dblclick='showInp1(index)' v-show='item.isEdit'>{{item.content}}</span>
<input type="text" @blur='item.isEdit=true' v-model='item.content' v-show='!item.isEdit'>
</li>
</ol>
<input type="text" v-model.trim='msg'><button @click='add'>添加</button>
<button @click='del'>删除已完成任务</button>
</div>
<script>
let vm = new Vue({
el:'#app',
data:{
lists:[
{isChecked:false,content:'学习java',isEdit:true},
{isChecked:false,content:'学习html',isEdit:true},
{isChecked:false,content:'学习vue',isEdit:true},
{isChecked:false,content:'学习css',isEdit:true}
],
msg:'',
id:0
},
methods:{
//添加任务
add(){
let obj = {
id:++this.id,
isChecked:false,
content:this.msg,
isEdit:true
}
this.lists.push(obj);
},
//定义双击任务时显示input输入框
showInp1(i){
//如果任务是已完成状态此时无法再次编辑
if(this.lists[i].isChecked) return;
//改变当前编辑的数据的isedit的值
this.lists[i].isEdit = false;
},
//任务总数
sum(){
return this.lists.length;
},
//未完成的任务
daiban(){
let aaa = 0;
this.lists.forEach(obj => {
if(!obj.isChecked){
aaa++;
}
});
return aaa;
},
//删除已完成任务
del(){
//通过原生js的数组的fillter方法筛选出未完成的任务
this.lists = this.lists.filter((obj)=>{
return obj.isChecked!=true;
})
}
}
})
</script>
</body>
</html>
- 点赞
- 收藏
- 关注作者
评论(0)