监听属性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监听计算属性改变。