VUE(二):
1.6 事件处理
1.6.1事件的基本使用:
- 使用
v-on:xxx
或@xxx
绑定事件,其中xxx是事件名 - 事件的回调需要配置在methods对象中,最终会在vm上
- methods中配置的函数,不要用箭头函数!否则this就不是vm了!!
- methods中配置的函数,都是Vue所管理的函数,this的指向是vm或组件实例对象
@click=“demo"
和@click="demo($event)"
效果一致,但是后者可以传参
<div id="root">
<h2>你好,{{name}}!</h2>
<!-- <button v-on:click="showInfo">点我提示信息</button> -->
<!-- 简写 -->
<button @click="showInfo1">点我提示信息</button>
<button @click="showInfo2(66,$event)">点我提示信息</button>
</div>
<script>
const vm = new Vue({
el:'#root',
data:{
name:'hxx'
},
methods: {
showInfo1(event){
alert('i love you')
},
showInfo2(number,event){
console.log(event,number);
// alert('i love you')
}
}
})
</script>
1.6.2 事件修饰符
Vue中的事件修饰符
-
prevent:阻止默认事件(常用)
//本来点击链接后会有点击事件再转发页面,但是prevent阻止了a的跳转(默认事件)
<!-- 阻止默认事件 --> <a href="http://www.baidu.com" @click.prevent="showInfo">点我呀~</a>
-
stop:阻止事件冒泡(常用)
//本来点button外面的div也会触发事件,但是我stop了
<!-- 阻止事件冒泡 --> <div class="demo1" @click="showInfo"> <button @click.stop="showInfo">点我嘛~</button> </div>
-
once:事件只触发一次(常用)
//再点button不起作用了
<button @click.once="showInfo">点我嘛~</button>
-
capture:使用事件的捕获模式
//冒泡:由内至外 捕获:有外到内
<div class="box1" @click.capture="showMsg(1)"> div1 <div class="box2" @click="showMsg(2)"> div2 </div> </div>
-
self:只有event.target是当前操作的元素时才触发事件
//点击button只会触发button的事件,因为事件的target是button,冒泡不上去(似乎和阻止冒泡有差不多的效果?)
<div class="demo1" @click.self="showInfo"> <button @click="showInfo">点我嘛~</button> </div>
-
passive:事件的默认行为立即执行,无需等待事件回调执行完毕
1.6.3 键盘事件
1.Vue中常用的按键别名:
回车 => enter
删除 => delete (删除或者退格键)
退出 => esc
空格 => space
换行 => tab ( 特殊,必须配合keydown使用)
上\下\左\右 => up\down\left\right
2.Vue未提供别名的按键,可以使用按键原始的key值去绑定,但注意要转为kebab-case(短横线命名)
3.系统修饰键(用法特殊):ctrl,alt,shift,win
(1) 配合keyup使用:按下修饰键的同时,再按下其他键,随后释放其他键,事件才被触发
(2) 配合keydown使用:正常触发事件
4.Vue.config.keyCodes.自定义按键名
= 键码,可以去定制按键别名
Vue.config.keyCodes.huiche = 13;//定义了一个回车的别名
1.7 计算属性与监视
1.7.1 姓名案例
1.method实现
<div id="root">
姓:<input type="text" v-model="firstName"><br/><br/>
名:<input type="text" v-model="lastName"><br/><br/>
全名:<span>{{fullName()}}</span>
</div>
<script>
new Vue({
el:'#root',
data:{
firstName:'张',
lastName:'三'
},
methods: {
fullName(){
return this.firstName+'-'+this.lastName
}
}
})
</script>
2.计算属性实现
<div id="root">
姓:<input type="text" v-model="firstName"><br/><br/>
名:<input type="text" v-model="lastName"><br/><br/>
全名:<span>{{fullName}}</span>
</div>
<script>
const vm = new Vue({
el:'#root',
data:{
firstName:'张',
lastName:'三'
},
computed: {
fullName:{
//get有什么作用?当有人读取fullName时,get就会被调用,且返回值就作为fullName的值
//get什么时候调用?1.初次读取fullName时 2.所依赖的数据发生改变时
get(){
console.log('get');
//this是vm
return this.firstName+'-'+this.lastName
},
//set什么使用调用?当fullName被修改时
set(value){
console.log('set',value)
const arr = value.split('-')
this.firstName = arr[0]
this.lastName = arr[1]
}
}
}
})
</script>
1.7.2 计算属性-computed:
1.定义:要用的属性不存在,要通过已有属性计算得来
2.原理:底层借助了Object.defineproperty
方法提供的getter
和setter
3.get函数什么时候执行?
(1).初次读取fullName时 (2).所依赖的数据发生改变时
4.优势:与methods实现相比,内部有缓存机制(复用),效率更高,调试更加方便
5.备注:(1).计算属性最终会出现在vm上,直接读取使用即可
(2).如果计算属性要被修改,那必须写set函数去响应修改,且set中要引起 计算式依赖的数据发生改变
计算属性的简写
computed: {
//简写:只考虑读取,不修改时
fullName:function(){
return this.firstName+'-'+this.lastName
}
}
1.7.3 监视属性-watch
1.当被监视的属性变化时,回调函数自动调用,进行相关操作
2.监视的属性必须存在,才能进行监视!!
3.监视的两种写法:
(1).new Vue时传入watch配置
watch:{
isHot:{
immediate:true,//初始化时让handler调用一下
//handler什么时候调用?当isHot发生改变时
handler(newValue,oldValue){
console.log('isHot被修改了',newValue,oldValue);
}
}
(2).通过vm.$watch监视
vm.$watch('isHot',{
immediate:true,//初始化时让handler调用一下
//handler什么时候调用?当isHot发生改变时
handler(newValue,oldValue){
console.log('isHot被修改了',newValue,oldValue);
}
})
4.深度监视
(1).Vue中的watch默认不监测对象内部值的改变(一层)
(2).配置deep:true
可以检测对象内部值改变(多层)
备注:(1)Vue自身可以检测对象内部值的改变,但Vue提供的watch默认不可以!
(2)使用watch时根据数据的具体结构,决定是否采用深度检测
watch:{
isHot:{
immediate:true,//初始化时让handler调用一下
//handler什么时候调用?当isHot发生改变时
handler(newValue,oldValue){
console.log('isHot被修改了',newValue,oldValue);
}
},
//监视多级结构中某个属性的变化
/* 'numbers.a':{
handler(){
console.log('a改变了');
}
} */
//监视多级结构中所有属性的变化
numbers:{
deep:true,
handler(){
console.log('numbers改变了');
}
}
}
(3)简写
形式一:
watch: {
//复杂写法:
isHot: {
//immediate: true, //初始化时先调用一次handler
//当isHot被修改时调用handler函数
handler(newVal, oldVal) {
console.log('isHot被修改了', '改之前是' + oldVal, '改之后是' + newVal);
}
},
//简写
// 如果handler函数中没有其他的配置项(deep,immediate等),可以简写成以下形式
isHot(newVal, oldVal) {
console.log('isHot被修改了', '改之前是' + oldVal, '改之后是' + newVal);
}
}
形式二:
//正常写法
vm.$watch('isHot', {
//当isHot被修改时调用handler函数
handler(newVal, oldVal) {
console.log('isHot被修改了', '改之前是' + oldVal, '改之后是' + newVal);
}
})
//简写
vm.$watch('isHot',function (newVaule,oldVaule) {
console.log(newVaule,oldVaule);
})
1.7.4 computed和watch之间的区别
1.computed能完成的功能,watch都能完成
2.watch能完成的功能,computed不一定能完成,例如:watch可以进行异步
操作
两个重要的小原则:
(1) 所被Vue管理的函数
,最好写成普通函数,这样this的指向才是vm 或 组件实例对象
(2) 所有不被Vue所管理的函数
(定时器的回调函数,ajax的回调函数等,promise的回调函数),最好写成箭头函数,这样this的指向才是vm 或 组件实例对象
1.8 样式绑定
1.8.1 绑定class样式
(1)字符串写法:适用于:样式类名不确定,需要动态指定
(2)数组写法,适用于:要绑定的样式个数不确定、名字也不确定
(3)对象写法,适用于:绑定的样式个数确定、名字也确定,但要动态决定要不要用
<div id="root">
<!-- 绑定class样式--字符串写法:适用于:样式类名不确定,需要动态指定 -->
<div class="basic" :class="mood" @click="changeMood">{{name}}</div>
<!-- 绑定class样式--数组写法,适用于:要绑定的样式个数不确定、名字也不确定 -->
<div class="basic" :class="classArr">{{name}}</div>
<!-- 绑定class样式--对象写法,适用于:绑定的样式个数确定、名字也确定,但要动态决定要不要用 -->
<div class="basic" :class="classObj" @click="changeMood">{{name}}</div>
<div class="basic" style="font-size: 40px;"></div>
</div>
<script>
new Vue({
el:'#root',
data:{
name:'test',
mood:'normal',
classArr:['test1','test2','test3'],
classObj:{
test1:false,
test2:false,
test3:true
}
},
methods: {
changeMood(){
const arr=['happy','normal','sad']
const x = Math.floor(Math.random()*3)
console.log(x);
this.mood = arr[x]
}
}
})
</script>
1.8.2 绑定style样式
<!-- 绑定style样式--对象写法 -->
<div class="basic" :style="styleObj">{{name}}</div>
<!-- 绑定style样式--数组写法 -->
<div class="basic" :style="styleArr">{{name}}</div>
<script>
new Vue({
el:'#root',
data:{
name:'test',
styleObj:{
fontSize:'40px',
color:'red'
},
styleObj2:{
backgroundColor:'orange'
},
styleArr:[
{
fontSize:'40px',
color:'blue'
},
{
backgroundColor:'green'
}
]
}
</script>
1.8.3 总结
1.class样式
写法:class=“xxx” xxx可以是字符串、对象、数组。
字符串写法适用于:类名不确定,要动态获取。
数组写法适用于:要绑定多个样式,但是不确定绑定哪几个,就写成数组,省的一个一个绑定。
对象写法适用于:要绑定多个样式,而且要动态决定用不用,这里面可以写一些判断的逻辑。
2.style样式
:style="{fontSize: xxx + 'px'}"其中xxx是动态值。
:style="[a,b]"其中a、b是样式对象
1.9 条件渲染
1.v-if
写法:
(1).v-if=“表达式”
(2).v-else-if=“表达式”
(3).v-else=“表达式”
适用于:切换频率较低的场景。(因为会动DOM树,节点删来删去不太好)
特点:不展示的DOM元素直接被移除。
注意:v-if可以和:v-else-if、v-else一起使用,但要求结构不能被“打断”。
2.v-show
写法:v-show=“表达式”
适用于:切换频率较高的场景。(不会动DOM树,只是隐藏,相当于添加display:none)
特点:不展示的DOM元素未被移除,仅仅是使用样式隐藏掉
备注:使用v-if的时,元素可能无法获取到,而使用v-show一定可以获取到。这是因为v-if会一不小心把标签直接从页面上干掉,而v-show不会干掉,只会隐藏。
<div id="root">
<!-- 1.v-show="false" => 相当于display:none -->
<h2 v-show="false">我的名字叫{{name}}</h2>
<h2 v-show="1 === 3">我的名字叫{{name}}</h2>
<!-- 等价于<h2 style="display: none;">我的名字叫{{name}}</h2> -->
<!-- 2.v-if="false" => 彻底删除标签了 -->
<h2 v-if="false">我的名字叫{{name}}</h2>
<h2 v-if="1 === 3">我的名字叫{{name}}</h2>
<!-- 实现功能:随着n递增展示不同的div -->
<h2>{{n}}</h2>
<button v-on:click="n++">点我n+1</button>
<!-- 这里的v-if,v-else-if,v-else和基础js里的一样儿 -->
<div v-if="n === 1">Angular</div>
<div v-else-if="n === 2">React</div>
<div v-else-if="n === 3">Vue</div>
<div v-else>hhhh</div>
<!-- v-if和template的配合使用(v-show不行)
template不会影响页面结构,页面运行后会自动去掉,但是可以配合v-if控制多个元素整体显示
而且不会影响css拿节点-->
<template v-if="n === 1">
<h2>1</h2>
<h2>2</h2>
<h2>3</h2>
</template>
</div>
<script>
const vm = new Vue({
el: '#root',
data: {
name: 'hxx',
n: 0
}
})
</script>