3.1 事件
3.1.1 事件的基本使用:
- 使用v-on:xxx 或 @xxx 绑定事件,其中xxx是事件名
- 事件的回调需要配置在methods对象中,最终会在vm上
- methods中配置的函数,都是被Vue所管理的函数,this的指向是vm 或 组件实例对象(不要用箭头函数!!!)
- @click='demo' 和 @click='demo($event)' 效果一致,但后者可以传参
<div id="root">
<h3>欢迎学习{{name}}</h3>
<button v-on:click="showInfo1">点我提示信息1(不传参)</button>
<!-- event用来占位,这样丢不了 -->
<button @click="showInfo2($event,66)">点我提示信息2(传参)</button>
</div>
<script src="./js/vue2.7.14.js"></script>
<script>
const vm = new Vue({
el: '#root',
data: {
name: 'vue'
},
methods: {
showInfo1(event) {
alert('你好')
// console.log(event.target.innerText) //点我提示信息
// console.log(this === vm) //true
},
showInfo2(event, number) {
console.log(event, number)
alert('你好!!')
// console.log(event.target.innerText) //点我提示信息
// console.log(this === vm) //true
}
}
})
</script>
3.1.2 事件修饰符
- prevent:阻止默认事件(常用)
- stop:阻止事件冒泡(常用)
- once:事件只触发一次(常用)
<div id="root">
<h3>欢迎{{name}}</h3>
<!-- 阻止默认行为 -->
<a href="http://www.baidu.com" @click.prevent="showInfo">点我到百度</a>
<!-- 阻止冒泡 -->
<div class="demo1" @click="showInfo">
<button @click.stop="showInfo">点我</button>
</div>
<!-- 事件只触发一次(once) -->
<button @click.once="showInfo">只触发一次</button>
</div>
<script src="./js/vue2.7.14.js"></script>
<script>
new Vue({
el: '#root',
data: {
name: 'zz'
},
methods: {
showInfo() {
//阻止默认行为
// e.preventDefault()
alert('你好')
}
}
})
</script>
3.1.3 键盘事件
@keydown,@keyup
Vue中常用的按键别名:
- 回车 => enter
- 删除 => delete
- 退出 => esc
- 空格 => space
- 换行 => tab (特殊,必须配合keydown去使用)
- 上下左右=>up/down/left/right
例:@keyup.enter="showInfo”
@keyup.caps-lock="showInfo”
<div id="root">
<h2>欢迎{{name}}</h2>
<input type="text" placeholder="按下回车提示键入" @keyup.caps-lock="showInfo">
</div>
<script>
// 创建 vm 实例对象
const vm = new Vue({
el: '#root',
data: {
name: 'zz'
},
methods: {
showInfo(e) {
// 按下回车(13)才能控制台输出
// if (e.keyCode !== 13) return
console.log(e.target.value)
}
}
});
</script>
3.2 计算属性——computed
--3.2.1插值语法实现{{}}
<div id="root">
姓: <input type="text" v-model:value="firstName"><br>
名: <input type="text" v-model:value="lastName"><br>
姓名:<span>{{firstName}}-{{lastName}}</span>
</div>
<script>
// 创建 vm 实例对象
const vm = new Vue({
el: '#root',
data: {
firstName: '张',
lastName: '三'
}
});
</script>
--3.2.2 methods
<div id="root">
姓: <input type="text" v-model:value="firstName"><br>
名: <input type="text" v-model:value="lastName"><br>
姓名:<span>{{fullName()}}</span>
</div>
<script>
// 创建 vm 实例对象
const vm = new Vue({
el: '#root',
data: {
firstName: '张',
lastName: '三'
},
methods: {
fullName() {
console.log('@---fullName') //每次输入都更新模板,效率不高
return this.firstName + '-' + this.lastName
}
}
});
</script>
methods 读5次被调用5次
--3.2.3 computed
计算属性:拿着已经写完的属性去加工,生成一个全新的属性
属性=>计算属性
<div id="root">
姓: <input type="text" v-model:value="firstName"><br>
名: <input type="text" v-model:value="lastName"><br>
测试: <input type="text" v-model:value="x"><br>
姓名:<span>{{fullName}}</span>
</div>
<script>
// 创建 vm 实例对象
const vm = new Vue({
el: '#root',
data: {
firstName: '张',
lastName: '三',
x: 'hello'
},
computed: {
fullName: {
//get的作用:当有人读取fullName时,get就会被调用,返回值就作为fullName的值
//get什么时候调用:1、初次读取fullName时,2、所依赖的数据发生变化时
get() {
console.log('get被调用了')
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>
计算属性读5次,但只调用1次,因为缓存
如果这个fullName只是读取给别人用的,那就可以只写get()。但是以后需要修改,就需要加上set()。
- 定义:要用的属性不存在,要通过已有属性计算得来
- 原理:底层借助了Objcet.defineProperty方法提供的getter和setter
- get函数什么时候执行? (1).初次读取时会执行一次 (2).当依赖的数据发生改变时会被再次调用
- 优势:与methods实现相比,内部有缓存机制(复用),效率更高,调试方便
- 备注:
(1)计算属性最终会出现在vm上,直接读取使用即可
(2)如果计算属性要被修改,那必须写set函数去响应修改,且set中要引起计算时依赖的数据发生改变
只读不改就可以使用简写模式
// 简写:
fullName() {
console.log('get被调用了')
return this.firstName + '-' + this.lastName
}
3.3 监视属性——watch
--3.3.1 天气案例
<div id="root">
<h2>今天天气很{{info}},{{x}}</h2>
<button @click='changeWeather'>切换天气</button>
<!-- <button @click='isHot = !isHot'>切换天气</button> -->
</div>
<script>
// 创建 vm 实例对象
const vm = new Vue({
el: '#root',
data: {
isHot: true,
x: 1
},
computed: {
info() {
return this.isHot ? '炎热' : '凉爽'
}
},
methods: {
changeWeather() {
this.isHot = !this.isHot
x++
}
}
});
</script>
--3.3.2 天气案例-监视属性
- 当被监视的属性变化时, 回调函数自动调用, 进行相关操作
- 监视的属性必须存在,才能进行监视!!‘info’
- 监视的两种写法:
- (1) new Vue时传入watch配置
- (2) 通过vm.$watch监视
<div id="root">
<h2>今天天气很{{info}}</h2>
<button @click='changeWeather'>切换天气</button>
</div>
<script>
// 创建 vm 实例对象
const vm = new Vue({
el: '#root',
data: {
isHot: true
},
computed: {
info() {
return this.isHot ? '炎热' : '凉爽'
}
},
methods: {
changeWeather() {
this.isHot = !this.isHot
}
},
// watch: {
// isHot: {
// immediate: true, //初始化时让handler调用一下
// // handler什么时候被调用:当isHot发生改变时。
// handler(newValue, oldValue) {
// console.log('isHot被修改了', newValue, oldValue)
// }
// }
// }
});
vm.$watch('isHot', {
immediate: true, //初始化时让handler调用一下
handler(newValue, oldValue) {
console.log('isHot被修改了', newValue, oldValue)
}
})
</script>
--3.3.3 深度监视
- Vue中的watch默认不监测对象内部值的改变(一层)
- 配置deep:true可以监测对象内部值改变(多层)
备注:
(1).Vue自身可以监测对象内部值的改变,但Vue提供的watch默认不可以
(2).使用watch时根据数据的具体结构,决定是否采用深度监视
<div id="root">
<h2>今天天气很{{info}}</h2>
<button @click='changeWeather'>切换天气</button>
<hr>
<h3>a的值是:{{numbers.a}}</h3>
<button @click="numbers.a++">点我让a+1</button>
<h3>b的值是:{{numbers.b}}</h3>
<button @click="numbers.b++">点我让b+1</button>
<button @click="numbers={a:123,b:456}">彻底替换掉numbers</button>
{{numbers.c.d.e}}
</div>
<script>
// 创建 vm 实例对象
const vm = new Vue({
el: '#root',
data: {
isHot: true,
// key:value
numbers: {
a: 1,
b: 1,
c: {
d: {
e: 300
}
}
}
},
computed: {
info() {
return this.isHot ? '炎热' : '凉爽'
}
},
methods: {
changeWeather() {
this.isHot = !this.isHot
}
},
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被改变了')
}
}
}
});
</script>
--3.3.4 监视简写
<div id="root">
<h2>今天天气很{{info}}</h2>
<button @click='changeWeather'>切换天气</button>
</div>
<script>
// 创建 vm 实例对象
const vm = new Vue({
el: '#root',
data: {
isHot: true
},
computed: {
info() {
return this.isHot ? '炎热' : '凉爽'
}
},
methods: {
changeWeather() {
this.isHot = !this.isHot
}
},
watch: {
// 正常写法
// isHot: {
// // immediate: true, //初始化时让handler调用一下
// // deep:true, //深度监视
// // handler什么时候被调用:当isHot发生改变时。
// handler(newValue, oldValue) {
// console.log('isHot被修改了', newValue, oldValue)
// }
// }
// 简写
isHot(newValue, oldValue) {
console.log('isHot被修改了', newValue, oldValue)
}
}
});
</script>
3.4computed和watch之间的区别:
- computed能完成的功能,watch都可以完成
- watch能完成的功能,computed不一定能完成,例如:watch可以进行异步操作
两个重要的小原则:
1.所被Vue管理的函数,最好写成普通函数,这样this的指向才是vm 或 组件实例对象
2.所有不被Vue所管理的函数(定时器的回调函数、ajax的回调函数等、Promise的回调函数),最好写成箭头函数,这样this的指向才是vm 或 组件实例对象
<div id="root">
姓: <input type="text" v-model:value="firstName"><br>
名: <input type="text" v-model:value="lastName"><br>
姓名:<span>{{fullName}}</span>
</div>
<script>
// 创建 vm 实例对象
const vm = new Vue({
el: '#root',
data: {
firstName: '张',
lastName: '三',
fullName: '张-三'
},
watch: {
// watch 监视器里可以写 异步函数
firstName(val) {
setTimeout(() => {
console.log(this)
this.fullName = val + '-' + this.lastName
}, 1000)
},
lastName(val) {
this.fullName = this.firstName + '-' + val
}
}
})
</script>
3.5 class与style绑定
--3.5.1 绑定class样式
正常的样式正常写,变化的样式v-bind绑定写
写法::class=“xxx” xxx可以是字符串、对象、数。
所以分为三种写法,字符串写法,数组写法,对象写法
<style>
.basic {
width: 200px;
height: 100px;
border: 1px black solid;
}
.happy {
background-image: linear-gradient(to right, red, yellow);
}
.sad {
background-color: gray;
}
.normal {
background-color: skyblue;
}
.zz1 {
background-color: lightcoral;
}
.zz2 {
font-size: 22px;
text-shadow: 2px 5px rgb(227, 76, 101);
}
.zz3 {
border-radius: 25px;
}
</style>
<div id="root">
<!-- 绑定class样式--字符串写法,适用于:样式的类名不确定,需要动态指定 -->
<div class="basic" :class="mood" @click="changeMood">{{name}}</div>
<br><br><br>
<!-- 绑定class样式--数组写法,适用于:要绑定的样式个数不确定、名字也不确定 -->
<div class="basic" :class="classArr">{{name}}</div>
<br><br><br>
<!-- 绑定class样式--对象写法,适用于:要绑定的样式个数确定、名字也确定,但要动态决定用不用 -->
<div class="basic" :class="classObj">{{name}}</div>
</div>
<script src="js/vue2.7.14.js"></script>
<script>
const vm = new Vue({
el: '#root',
data: {
name: 'zz',
mood: 'normal',
classArr: ['zz1', 'zz2', 'zz3'],
classObj: {
zz1: false,
zz2: false
}
},
methods: {
changeMood() {
// this.mood = 'happy'
const arr = ['happy', 'sad', 'normal']
const index = Math.floor(Math.random() * 3)
this.mood = arr[index]
}
}
})
</script>
--3.5.2 绑定style样式
<div class="basic" :style="styleObj">{{name}}</div>
<div class="basic" :style="[styleObj,styleObj2]">{{name}}</div>
const vm = new Vue({
el: '#root',
data: {
name: 'zz',
mood: 'normal',
styleObj: {
fontSize: '30px',
color: 'red'
},
styleObj2: {
backgroundColor: 'pink'
}
}