Vue学习计划-Vue2--Vue核心(四)watch监听属性、动态绑定class、style,set方法的使用
1. 监听(watch)
: 监听一个属性的变化,又叫监听器,侦听器
-
监视属性
watch
:- 当监视的属性变化时,回调函数自动调用,进行相关操作
- 监视的属性必须存在,才能进入监视
- 监视的两种写法:
new Vue
时传入watch
配置- 通过
vm.$watch()
监视
immediate
初始化时让handler
调用一下
-
深度监视:
Vue
中的watch
默认不监视对象内部值的变化(只监视一层)- 配置
deep:true
可以监视对象内部值变化(监视多层结构)
-
监视
watch
有两种完整写法:
1. 在Vue实例内部
const vm = new Vue({
el: "#app",
watch:{
immediate: true, // 初始化时让handler调用一下
deep: true, // 深度监听
handler(newValue, oldValue){
console.log(newValue, oldValue)
}
}
})
2. 实例身上调用$watch API
vm.$watch('isSHow',{
immediate: true, // 初始化时让handler调用一下
deep: true, // 深度监听
handler(newValue, oldValue){
console.log(newValue, oldValue)
}
})
- 监视对应的有两种简写:当确定不使用
immediate
和deep
属性时可以简写
1. 写在Vue实例内部
const vm = new Vue({
el: "#app",
watch:{
isShow(newValue, oldValue){
console.log(newValue, oldValue)
}
}
})
2. 实例身上调用$watch API
vm.$watch('isSHow', function(newValue, oldValue){
console.log(newValue, oldValue)
})
-
备注:
Vue
自身可以监视对象内部值得变化,但Vue提供的watch默认不可以- 使用
watch
时,根据数据的具体结构,决定是否采用深度监听
-
计算属性
(computed)
、方法methods
、监听(watch)
的区别?computed、watch、methods
专人干专事- 计算属性
computed
:- 目的是得到一个计算结果,必须要有return,一个状态值受多个状态值影响。
- 有缓存,当依赖状态值变化是,才会重新计算。
- 不能异步
- 本身不支持传参,可以使用闭包
- 事件
methods
:- 绑定的事件处理,非必须
return
- 没有缓存
- 绑定的事件处理,非必须
- 监听
watch
:- 一个状态的改变 影响多条数据,没有
return
- 没有缓存
- 可以异步
- 不传参
- 一个状态的改变 影响多条数据,没有
- 计算属性
2. 标签体上动态class和style
绑定
class
样式 写法::class = "xxx"
,xxx
可以是字符串、对象、数组- 字符串写法适用于:类名不确定,要动态获取
- 对象写法适用于:要绑定多个样式,个数不确定,名字也不确定
- 数组写法适用于:要绑定多个样式,个数确定,名字也确定
style
样式
示例::style = "{fontSize: xxx}" 其中xx是动态的 :style = "[a, b]" 其中a, b是样式对象
<!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> /* #region */ .red{ color: red; } .blue{ color: blue; } .green{ color: green } .yellow{ color: yellow } /* #endregion */ .bold{ font-weight: bold; } .size{ font-size: larger; } </style> </head> <body> <div id="app"> <!-- 1. 绑定字符串 --> <!-- 1.1.1 固定切换class名称 --> <p :class="name">这是一个动态class</p> <button @click="changClass">点击单次切换class名</button> <br> <!-- 1.1.2 随机切换class名称 --> <!-- class 和:class 可以绑定多个class名称 --> <p class="bold" :class="name">这是一个动态class</p> <button @click="changClass2">点击数组切换class名</button> <br> <!-- 1.1.3 三元表达式表达式切换class名称 --> <p :class="isName ? 'red' : 'blue'">这是一个动态class</p> <button @click="isName = !isName">表达式切换class名</button> <hr> <!-- 2. 绑定对象 --> <!-- <p :class="{bold: true, size: false}">这是一个对象绑定的class类名</p> --> <p :class="objClass">这是一个对象绑定的class类名</p> <button @click="objClassChange">表达式切换class名</button> <hr> <!-- 3. 绑定数组 --> <!-- <p :class="['blue', 'bold', 'size']">这是一个对象绑定的class类名</p> --> <p :class="arrClass">这是一个对象绑定的class类名</p> <button @click="arrClassChange">表达式切换class名</button> </div> <script> const vm = new Vue({ el: '#app', data: { name: 'red', isName: true, arr:['red', 'blue', 'green'], // 对象class名称 objClass:{ red: true, bold: true }, // 数组class名称 arrClass:[ 'blue', 'bold', 'size'] }, methods: { // #region 字符串绑定 changClass(){ this.name = 'blue' }, changClass2(){ const a = Math.floor(Math.random() * 3) console.log(this.arr[a]); this.name = this.arr[a] }, // #endregion objClassChange(){ // this.objClass.size = true // 解决方法 $set方法 // this.$set(this.objClass, 'size', true) Vue.set(this.objClass, 'size', true) }, arrClassChange(){ // this.arrClass.splice(0, 1, 'yellow') // 存在问题?为何vm中的arrClass值改变了,页面却没有渲染 => Vue内部监视原理 // this.arrClass[0] = 'yellow' // 解决方法 // this.$set(this.arrClass, 0, 'yellow') this.$set(this.arrClass, 0, 'yellow') } }, }) </script> </body> </html>
3. set
方法的使用
Vue
会监视data
中所有层次的数据。- 如何监视对象的数据? 通过
setter
实现监视,且要在new Vue
时就传入要监测的内容- 对象中后追加的属性,
Vue
默认不做响应式处理 - 如需要给后添加的属性做响应式,使用如下
API
:Vue.set(target, propertyName/index, value) vm.$set(target, propertyName/index, value)
- 对象中后追加的属性,
示例:
<body>
<div id="app">
{{ obj }}
<button @click="changeObj">点击改变obj值</button>
</div>
<script>
const vm = new Vue({
el: '#app',
data:{
obj:{
name: '小明'
}
},
methods: {
changeObj(){
// this.obj.banji = 'xx班级' // 后添加的数据不会是响应式的
// 解决方法
// this.$set(this.obj, 'banji', 'xx班级')
Vue.set(this.obj, 'banji', 'xx班级')
},
},
})
</script>
</body>
- 如何监视数组中的数据? 通过包裹数组更新元素的方法实现,本质就是做两件事
1. 调用原生对应的方法对数组进行更新
2. 重新解析模板,进而更新页面
- 在Vue修改数组中的某个元素一定要用如下方案:
- 使用这些API:
push()
,pop()
,shift()
,unshift()
,sort()
,reverse()
,splice()
- 使用这些API:
- **
Vue.set()
或者vm.$set()
**的使用场景- 给对象新添的属性处理成响应式数据
- 给数组的添加响应式数据
特别注意:Vue.set()和vm.$set()不能给vm或者vm的根数据对象添加属性!!
示例:
<body>
<div id="app">
{{ arr }}
<button @click="changeArr">点击改变arr值</button>
<hr>
{{ arr2 }}
<span v-once>{{ arr2 }}</span>
<button @click="changeArr2">点击改变arr顺序sort方法</button>
<hr>
{{ arr3 }}
<button @click="changeArr3">点击翻转arr</button>
</div>
<script>
const vm = new Vue({
el: '#app',
data:{
arr:['小亮', 10],
arr2:[ 10, 40, 5, 30],
arr3:[ 1, 2, 3, 4]
},
methods: {
changeArr(){
// this.arr[0] = '小白'
// 解决方法一: set
// this.$set(this.arr, 2, 'xx班级')
// Vue.set(this.arr, 2, 'xx班级')
// this.arr[2] = '小白'
// 解决方法二:内置函数
// 1. 数组后添加值
// this.arr.push('小白')
// 2. 数组后删除值
// this.arr.pop()
// 3. 从头往后删除数组
// this.arr.shift()
// 4. 数组前面加值
// this.arr.unshift('小小')
},
// 数组排序
changeArr2(){
// 5. sort()
// 正序
this.arr2.sort((a,b) =>{
console.log('--');
console.log(a, b);
return a-b
})
// this.arr2.sort((a,b) =>{
// return b - a
// })
},
// 翻转数组
changeArr3(){
// this.arr3.reverse()
// this.arr3.splice(1, 2, 'a', 'b', 'v')
// 注意: 禁止给vm或者vm的跟数据对象添加属性
// console.log(vm._data)
// this.$set(vm._data, 'name', 'ssss')
// this.$set(vm, 'name', 'ssss')
}
},
})
</script>
</body>