监听属性watch
计算属性computed
一、监听属性watch
watch 的第一个参数可以是不同形式的“数据源,watch 可以监听以下几种数据:
一个 ref (包括计算属性)、 一个响应式对象、 一个 getter 函数、
或多个数据源组成的数组
watch 的参数:监视的回调,配置对象(deep:深度监听、immediate:立即执行…)
1、监听单个ref对象
<script setup>
import { ref ,reactive, watch } from 'vue';
const num = ref(0);
//watch参数被监视的数据,监视的回调,配置对象(deep:深度监听、immediate:立即执行.....)
const stopWatch = watch(num,(newValue,oldValue)=>{
console.log('num新数据:'+newValue,'num旧数据:'+oldValue)
})
const onNumAdd = ()=>{
num.value++;
}
</script>
<template>
<div>
<div>监听属性watch:{{num}}</div>
<button @click="onNumAdd()">num+1</button>
</div>
</template>
2、监听单个 ref 对象类型 数据
如果我们直接像监听单个ref基础数据类型写,是监听不到数据的,此时我们需要手动加上deep深度监听
<script setup>
import { ref ,reactive, watch } from 'vue';
const user = ref({
name:'zhangsan'
});
const stopWatch = watch(user,(newValue,oldValue)=>{
console.log('user新数据:'+newValue.name,'user旧数据:'+oldValue.name)
},{deep:true})
const onchangeName = ()=>{
user.value.name = 'lisi';
}
</script>
<template>
<div>
<div>监听属性watch:{{user.name}}</div>
<button @click="onchangeName()">修改名字</button>
</div>
</template>
可以看出若修改的是ref定义的对象中的属性,newValue 和 oldValue 都是对应的新值,因为它们是同一个对象;若修改整个ref定义的对象,newValue 是新值, oldValue 是旧值,因为不是同一个对象了
3、监听 reactive 对象类型数据
<script setup>
import { ref ,reactive, watch } from 'vue';
const user = reactive({
name:'zhangsan',
age:20
});
const stopWatch = watch(user,(newValue,oldValue)=>{
console.log('新数据:'+newValue.name,'-----旧数据:'+oldValue.name)
})
const onchangeName = ()=>{
user.name = 'lisi';
}
const onchangeAge = ()=>{
user.age = '22';
}
</script>
<template>
<div>
<div>监听属性watch----{{user.name}}-----{{user.age}},</div>
<button @click="onchangeName()">监听名字</button>
<button @click="onchangeAge()">监听年龄</button>
</div>
</template>
我们发现不需要像ref对象类型添加deep,因为默认开启深度监听
4、监听多个数据
监视多个数据,直接把所有数据放到数组中
<script setup>
import { ref ,reactive, watch } from 'vue';
const num = ref(0);
const user = reactive({
name:'zhangsan',
age:20
});
const stopWatch = watch([num,()=>user.name,()=>user.age],(newValue,oldValue)=>{
console.log('新数据:'+newValue,'-----旧数据:'+oldValue) //newValue[0]对应监听的第一个数据源
})
const onchange = ()=>{
num.value ++;
user.name = 'zhangsan修改';
user.age = '20';
}
</script>
<template>
<div>
<div>监听属性watch--{{num}}--{{user.name}}-----{{user.age}},</div>
<button @click="onchange()">监听多值</button>
</div>
</template>
5、监听对象的某个属性
监听ref或者reactive定义的对象类型数据中的某个属性时,如果该属性值不是对象类型,需要写成函数的形式,如果是对象类型,可以直接写,也可以写成函数的形式
<script setup>
import { ref ,reactive, watch } from 'vue';
const user = reactive({
name:'zhangsan',
age:20
});
const stopWatch = watch(()=>user.name,(newValue,oldValue)=>{
console.log('新数据:'+newValue,'-----旧数据:'+oldValue)
})
const onchangeName = ()=>{
user.name = 'lisi';
}
const onchangeAge = ()=>{
user.age = '22';
}
</script>
<template>
<div>
<div>监听属性watch----{{user.name}}-----{{user.age}},</div>
<button @click="onchangeName()">监听名字</button>
<button @click="onchangeAge()">监听年龄</button>
</div>
</template>
6、 watchEffect()
watchEffect也是用来监听数据的,刚进页面就会立即执行一次,同时响应式地追踪其依赖,并在依赖更改时重新执行该函数。
watch要明确指出监听的数据,watchEffect不用明确指定监视的数据,用到哪些属性,就会监听哪些属性。
<script setup>
import { ref ,reactive, watch ,watchEffect } from 'vue';
const num = ref(0);
const user = reactive({
name:'zhangsan',
age:20
});
const stopWatch = watchEffect(()=>{
console.log('数据发生变化:'+num.value,user.name)
})
const onchange = ()=>{
num.value ++;
user.name = 'zhangsan修改';
}
</script>
<template>
<div>
<div>监听属性watch--{{num}}--{{user.name}}-----{{user.age}},</div>
<button @click="onchange()">改变</button>
</div>
</template>
7、停止监听
有的时候,我们可能只需要监听一次。在监听之后,我们就需要取消对watch的监听。此时我们可以这样做,将watch监听器赋值给一个变量,在取消监听的时候调用此变量即可。
要手动停止一个侦听器,请调用 watch 或 watchEffect 返回的函数:
<script setup>
import { ref ,reactive, watch ,watchEffect } from 'vue';
const num = ref(0);
const stopWatch = watch(num,(newValue,oldValue)=>{
console.log('新数据:'+newValue,'旧数据:'+oldValue)
//停止监听
if(newValue == 5)
stopWatch()
})
const onchange = ()=>{
num.value ++;
}
</script>
二、计算属性computed
计算属性computed作用是根据已有数据计算出新数据。它需要返回一个值,返回的值就是该计算属性的值。
1、只读取
<script setup>
import { reactive, computed } from 'vue'
const author = reactive({
name: 'zhangsan',
books: [
'Vue 2',
'Vue 3',
'Vue 4'
]
})
// 一个计算属性 ref
const BooksMessage = computed(() => {
return author.books.length > 0 ? 'Yes' : 'No'
})
</script>
<template>
<p>计算属性:</p>
<span>{{ BooksMessage }}</span>
</template>
2、可写计算属性
计算属性默认是只读的。当你尝试修改一个计算属性时,你会收到一个运行时警告。只在某些特殊场景中你可能才需要用到“可写”的属性,你可以通过同时提供 getter 和 setter 来创建
<script setup>
import { ref, computed } from 'vue'
const age = ref(16)
const newAge = computed({
// get函数,获取计算属性的值
get(){
return age.value + 2
},
// set函数,当你给计算属性设置值的时候触发
set (value) {
age.value = value - 2
}
})
</script>
<template>
<p>计算属性:</p>
<div class="container">
<div>今年:{{age}}岁</div>
<div>后年:{{newAge}}岁</div>
<input type="text" v-model="newAge">
</div>
</template>
总结:
给computed传入函数,返回值就是计算属性的值
给computed传入对象,get获取计算属性的值,set监听计算属性改变。