3.1监视属性:
1.当被监视的属性变化时,回调函数自动调用,进行相关操作;
2.监视的属性必须存在,才能进行监视!
3.监视的两种写法:
(1)new Vue时传入watch配置;
(2)通过vm.$watch监视
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>监视属性</title>
<script type="text/javascript" src="../js/vue.js"></script>
</head>
<body>
<div id="root">
<h2>今天天气{{info}}</h2>
<button @click="changeWeather">click to change</button>
<!-- <button @click="isHot = !isHot">click to change</button>-->
</div>
<script type="text/javascript">
Vue.config.productionTip= false
const vm = new Vue({
el:'#root',
data:{
isHot:true
},
computed:{
info(){
return this.isHot? 'hot' : 'cold';
}
},
methods:{
changeWeather(){
this.isHot = !this.isHot
}
},
watch:{
// info:{
// immediate:true,
// handler(newEl,oldEl){
// console.log("isHot is changed,new Element is "+ newEl +", old Element is " + oldEl)
// }
// },
//new Vue时传入watch配置;
// isHot:{
// immediate:true,
// handler(newEl,oldEl){
// console.log("isHot is changed,new Element is "+ newEl +", old Element is " + oldEl)
// }
// },
}
})
//通过vm.$watch监视
vm.$watch('isHot',{
immediate:true,
handler(newEl,oldEl){
console.log("isHot is changed,new Element is "+ newEl +", old Element is " + oldEl)
}
})
</script>
</body>
</html>
深度监视:
1.Vue中的watch默认不检测对象内部值的改变(一层)。
2.配置deep:true可以检测对象内部值的改变(多层)。
3.Vue自身可以检测对象内部值的改变,但Vue提供的watch默认不可以!
4.使用Watch时根据数据的具体结构,决定是否采用深度监视。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>监视属性2</title>
<script type="text/javascript" src="../js/vue.js"></script>
</head>
<body>
<div id="root">
<h2>今天天气{{info}}</h2>
<button @click="changeWeather">click to change</button>
<br>
<h3>a's value is {{numbers.a}}</h3>
<button @click="numbers.a++">click to change a</button>
<h3>b's value is {{numbers.b}}</h3>
<button @click="numbers.b++">click to change b</button>
<button @click="numbers = {a:666,b:888}">total change numbers</button>
</div>
<script type="text/javascript">
Vue.config.productionTip= false
const vm = new Vue({
el:'#root',
data:{
isHot:true,
numbers:{
a:1,
b:2,
c:3
}
},
computed:{
info(){
return this.isHot? 'hot' : 'cold';
}
},
methods:{
changeWeather(){
this.isHot = !this.isHot
}
},
watch:{
'isHot':{
//在数值改变前就开始监视
immediate:true,
handler(newEl,oldEl){
console.log("isHot is changed,new Element is "+ newEl +", old Element is " + oldEl)
}
},
'numbers.a':{
handler(newEl, oldEl) {
console.log(newEl)
}
},
'numbers.b':{
handler(newEl,oldEl){
console.log(newEl)
}
},
numbers: {
// deep watch
deep:true,
handler(newEl,oldEl){
console.log("numbers is changed"+ newEl)
}
}
}
})
</script>
</body>
</html>
监视的简写形式:
watch:{
//normal
'isHot':{
immediate:true,
handler(newEl,oldEl){
console.log("isHot is changed,new Element is "+ newEl +", old Element is " + oldEl)
}
},
//simple
'isHot'(newEl,oldEl){ // equals handler
console.log("isHot is changed,new Element is "+ newEl +", old Element is " + oldEl)
}
}
vm.$watch("isHot",{
immediate:true,
handler(newEl,oldEl){
console.log("isHot is changed,new Element is "+ newEl +", old Element is " + oldEl)
}
})
//simple
vm.$watch('isHot',function (newEl,oldEl) {
console.log("isHot is changed,new Element is "+ newEl +", old Element is " + oldEl)
})
3.2 计算属性和监视属性的辨析
监视属性实现的姓名案例:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>监视属性</title>
<script type="text/javascript" src="../js/vue.js"></script>
</head>
<body>
<div id="root">
you first name is <input type="text" v-model:value="firstName"> <br> <br>
you last name is <input type="text" v-model:value="lastName"> <br> <br>
full name is : <span>{{fullName}}</span>
</div>
<script type="text/javascript">
Vue.config.productionTip= false
const vm = new Vue({
el:'#root',
data:{
firstName:'Excaliba',
lastName:'Joy',
fullName: 'Excaliba-Joy',
},
computed:{
// fullName(){
// return this.firstName + "-" + this.lastName;
// }
},
methods:{
},
watch:{
firstName(newValue,oldValue){
this.fullName = newValue + "-" + this.lastName;
},
lastName(newValue,oldValue){
this.fullName = this.firstName + "-" + newValue;
}
}
})
</script>
</body>
</html>
和之前计算属性的版本对比,显然代码变多了,但是计算属性中是不能异步执行的,因为计算属性中有返回值,而监视属性没有返回值,可以使用异步执行。
watch:{
firstName(newValue,oldValue){
//异步执行,有一秒的延迟
setTimeout(()=>{
this.fullName = newValue + "-" + this.lastName;
},1000);
},
lastName(newValue,oldValue){
this.fullName = this.firstName + "-" + newValue;
}
}
总结:
二者之间的区别:
1.computed能完成的功能,watch都能完成;
2.watch能完成异步的操作;
小知识点:
1.被Vue所管理的函数,最好写成普通函数,这样它的this就是Vue实例 或 组件的实例对象;
2.不被Vue所管理的函数(某些回调函数。定时器,Ajax等),最好写成箭头函数,这样它的this才是Vue实例 或 组件的实例对象。
3.3 class与style的绑定
1.Class样式
写法: :class=“xxx” xxx可以是字符串,对象,数组
字符串写法适用于:类名不确定,要动态获取。
对象写法适用于:要绑定多个样式,样式名称不确定。数量也不确定。
数组写法适用于:要绑定多个样式,个数确定,名字也确定,但不确定用不用。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<script src="../js/vue.js" type="text/javascript"></script>
<style>
.basic{
width: 400px;
height: 200px;
border: 5px double cadetblue;
}
.bg1{
background-color: brown;
}
.bg2{
background-color: coral;
}
.font1{
font-family: C059;
}
.font2{
font-size: 30px;
}
.font3{
color: chartreuse;
}
</style>
<title>Hello Vue</title>
</head>
<body>
<div class="root">
<div :class="{basic: isBasic, bg1: isBg1, bg2: isBg2}">Hello {{name}}</div>
<button @click="changeBg"> click me to change background </button>
<!-- 绑定class样式 对象写法,适用于 要绑定的样式个数确定,名字也确定,但要动态决定用不用-->
<div class="basic" :class="classObj">Hello {{name}}</div>
<button @click="changeBg2"> click me to change background </button>
<br>
<!-- 绑定class样式 数组写法,适用于 要绑定的样式个数不确定,名字也不确定-->
<div class="basic bg1" :class="arr" @click="changeFont1"> div2 </div>
<!-- style bind-->
<!-- style object-->
<div class="basic" :style="styleObj">{{name}} and 5</div>
<!-- style array-->
<div class="basic" :style="[styleObj,styleObj2]">{{name}} and 6</div>
</div>
<!-- 绑定class样式 字符串写法,适用于样式的类名不确定,需要动态指定-->
<div class="root02">
<h1 class="basic" :class="Bg">Hello {{name}}</h1>
<button @click="changeBg"> click me to change background </button>
</div>
<script type="text/javascript">
Vue.config.productionTip = false
//Vue instance
const x = new Vue({
// el:document.getElementById('root') the same
el:".root",
data:{
name:'Vue2',
isBasic:true,
isBg1:false,
isBg2:true,
Bg:'bg1',
arr:['font1','font2','font3'],
classObj:{
bg1:false,
bg2:true,
},
styleObj:{
fontSize:'40px'
},
styleObj2:{
backgroundColor:'red'
}
},
methods:{
changeBg(){
let mid = this.isBg1;
this.isBg1 = this.isBg2;
this.isBg2 = mid;
},
changeBg2(){
let mid = this.classObj.bg1;
this.classObj.bg1 = this.classObj.bg2;
this.classObj.bg2 = mid;
},
changeFont1(){
this.arr.pop()
}
}
})
const vm = new Vue({
// el:document.getElementById('root') the same
el:".root02",
data:{
name:'Vue2',
Bg:'bg1',
},
methods:{
changeBg(){
if (this.Bg === 'bg1'){
this.Bg = 'bg2';
}else {
this.Bg = 'bg1';
}
},
}
})
</script>
</body>
</html>