Vue3 Day4-计算、监视属性
4.1 computed计算属性
简写形式和全写形式
<template><div>person.firstName:<input type="text" v-model="person.firstName" /><br />person.lastName:<input type="text" v-model="person.lastName" /><br />fullName:<input type="text" v-model="fullName" /></div>
</template>
<script setup>import {ref,reactive,computed} from 'vue'
let person = reactive({firstName: '吴',lastName: '老'})
// 简写形式:里面是箭头函数// let fullName = computed(() => {// return person.firstName + '-' + person.lastName// })
// 全写形式:里面是对象写法let fullName = computed({get: () => {return person.firstName + '-' + person.lastName},set: (val) => {let nameArr = val.split('-') //将val字符串转成数组person.firstName = nameArr[0] //将改变的第一个名重新赋给person.firstNameperson.lastName = nameArr[1]}})
</script>
<style scoped>
</style>
4.2 watch监视属性
1.监视ref定义基本数据类型的响应式数据
<template><div><!-- 情况1:监视ref定义基本数据类型的响应式数据 --><h2>{{num}}</h2><button @click="numAdd">num++</button></div>
</template>
<script setup>import {ref,reactive,watch} from 'vue'
let num = ref(12)let numAdd = () => {num.value++}watch(num, (newval, oldval) => {console.log('oldval', oldval);console.log('newval', newval);}, {immdeiate: true})
</script>
<style scoped>
</style>
2.监视ref定义的某些基本数据类型的响应式数据
<template><div><!-- 情况2:监视ref定义的某些基本数据类型的响应式数据 --><h2>{{num}}</h2><h2>{{msg}}</h2><button @click="infoAdd">info++</button></div>
</template>
<script setup>import {ref,reactive,watch} from 'vue'
let num = ref(12)let msg = ref('小孩姐')let infoAdd = () => {num.value++msg.value += '@'}
// 方式1:分开监听// watch(num, (newval, oldval) => {// console.log('oldval', oldval);// console.log('newval', newval);// }, {// immdeiate: true// })// watch(msg, (newval, oldval) => {// console.log('oldval', oldval);// console.log('newval', newval);// }, {// immdeiate: true// })
// 方式2:合并监听watch([num, msg], (newval, oldval) => {console.log('oldval', oldval);console.log('newval', newval);}, {immediate: true})
</script>
<style scoped>
</style>
3.监视ref定义的对象数据类型的响应式数据
<template><div><!-- 情况3:监视ref定义的对象数据类型的响应式数据 --><h2>{{info.name}}</h2><h2>{{info.age}}</h2><button @click="infoAdd">info++</button></div>
</template>
<script setup>import {ref,reactive,watch} from 'vue'
let info = ref({name: '小孩姐',age: 12})let infoAdd = () => {info.value.name += '@'info.value.age++}
// 监视ref定义的对象类型,必须添加deep深度监听;如果想监听到新老值,那必须监听里面的某个值(箭头函数写法),或者用数组的方法来监听某些值watch([() => info.value.name, () => info.value.age], (newval, oldval) => {console.log("oldval=>", oldval);console.log("newval=>", newval);}, {deep: true})
</script>
<style scoped>
</style>
4.监视reactive定义的响应式数据
<template><div><!-- 情况4:监视reactive定义的响应式数据 --><h2>{{info.name}}</h2><h2>{{info.age}}</h2><h2>{{info.job.work.year}}</h2><button @click="infoAdd">info++</button></div>
</template>
<script setup>import {ref,reactive,watch} from 'vue'
let info = reactive({name: '小孩姐',age: 12,job: {work: {year: 3}}})let infoAdd = () => {info.name += '@'info.age++info.job.work.year++}
// 子情况1:监视reactive定义的响应式数据中的某些属性,deep无法关闭它是自动开启的// watch([() => info.name, () => info.age, () => info.job.work.year], (newval, oldval) => {// console.log('oldval=>', oldval);// console.log('newval=>', newval);// }, {// immediate: true// })
// 子情况2:监视的内容下面还有更深层次的内容 那么就需要用到deep,否则无效watch([() => info.job], (newval, oldval) => {console.log('oldval=>', oldval);console.log('newval=>', newval);}, {immediate: true,deep: true})
</script>
<style scoped>
</style>
4.3 watchEffect的使用
watchEffect能够立即监听 同时是深度监听并可以监听到新老值
<template><div><!-- watchEffect的使用 --><h2>{{info.name}}</h2><h2>{{info.age}}</h2><h2>{{info.job.work.year}}</h2><button @click="infoAdd">info++</button></div>
</template>
<script setup>import {ref,reactive,watch,watchEffect} from 'vue'
let info = reactive({name: '小孩姐',age: 12,job: {work: {year: 3}}})let infoAdd = () => {info.name += '@'info.age++info.job.work.year++}// watchEffect能够立即监听 同时是深度监听并可以监听到新老值watchEffect(() => {let val1 = info.agelet val2 = info.job.work.yearconsole.log('val1', val1);console.log('val2', val2);})
</script>
<style scoped>
</style>
4.4 watch对比watchEffect
1.watch 和 watchEffect 都能监听响应式数据的变化,不同的是它们监听数据变化的方式不同。watch 会明确监听某一个响应数据,而 watchEffect 则是隐式的监听回调函数中响应数据。 2.watch 在响应数据初始化时是不会执行回调函数的,watchEffect 在响应数据初始化时就会立即执行回调函数。
注意:
-
onInvalidate:副作用清理函数
-
watchPostEffect() 是watchEffect() 使用 flush: 'post' 选项时的别名
<template><div><h2 ref="hbu">{{num}}</h2><button @click="infoAdd">info++</button></div>
</template>
<script setup>import {ref,reactive,watch,watchEffect,watchPostEffect} from 'vue'
let num = ref(12)let hbu = ref()let infoAdd = () => {num.value++}
//onInvalidate:副作用清理函数// watch(num, (newval, oldval, onInvalidate) => {// console.log('小孩哥');// console.log('DOM节点:', hbu.value.innerText);// onInvalidate(() => {// console.log('我是清理副作用的代码');// })// }, {// flush: 'post'// })
// watchEffect写法:// watchEffect(onInvalidate => {// console.log(num.value);// console.log('DOM节点:', hbu.value.innerText);// onInvalidate(() => {// console.log('我是清理副作用的代码');// })// }, {// flush: 'post'// })
// watchPostEffect() 是watchEffect() 使用 flush: 'post' 选项时的别名// watchPostEffect写法:watchPostEffect(onInvalidate => {console.log(num.value);console.log('DOM节点:', hbu.value.innerText);onInvalidate(() => {console.log('我是清理副作用的代码');})})
</script>
<style scoped>
</style>
4.5 nextTick以及watchPostEffect的使用
两者都可以立即监视到数据的变化
<template><div><button ref="hbu" @click="change">{{content}}</button></div>
</template>
<script setup>import {ref,reactive,watch,watchEffect,watchPostEffect,nextTick} from 'vue'
let content = ref('改变我吧')let hbu = ref(null)let change = () => {content.value = '我是改变后的'// console.log(hbu.value.innerText); //改变我吧
// 1.nextTick()// nextTick(() => {// console.log(hbu.value.innerText); //我是改变后的// })}
// 2.watchPostEffect()watchPostEffect(() => {console.log('watchEffect=>', hbu.value.innerText);console.log('watchEffect=>', content.value);})
</script>
<style scoped>
</style>