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.firstName
person.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.age
let val2 = info.job.work.year
console.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>