1. computed
1. computed
<template>
<input v-model="person.firstName" />
<br />
<input v-model="person.lastName" />
<div>全名: {{ person.fullName }}</div>
<input v-model="person.fullName" />
</template>
<script>
import { reactive, computed } from 'vue'
export default {
name: 'DemoComponent',
// vue2计算属性的写法
// computed: {
// fullName() {
// return `${this.person.firstName}-${this.person.lastName}`
// }
// },
setup() {
const person = reactive({
firstName: '张',
lastName: '三'
})
// 计算属性 - 简写
// person.fullName = computed(() => {
// return `${person.firstName}-${person.lastName}`
// })
// 计算属性 - 完整
person.fullName = computed({
get() {
return `${person.firstName}-${person.lastName}`
},
set(value) {
const arr = value.split('-');
person.firstName = arr[0]
person.lastName = arr[1]
}
})
return {
person,
}
}
}
</script>
2. watch监听ref和reactive响应式数据基本用法
watch函数两个小坑:
1. 监视reactive定义的响应式数据时,oldValue无法正确获取,且强制开启了深度监视(deep配置无效)
2. 监视reactive定义的响应式数据中的某个属性时(非对象时),deep配置有效
代码演示如下:
<template>
<div>{{ sum }}</div>
<button @click="sum++">sum按钮</button>
<div>{{ msg }}</div>
<button @click="msg += `!`">msg按钮</button>
<hr />
<div>{{ person.name }}</div>
<button @click="person.name += '~'">按钮name</button>
<div>{{ person.job.j1.salary }}</div>
<button @click="person.job.j1.salary++">按钮salary</button>
</template>
<script>
import { reactive, ref, watch } from 'vue'
export default {
name: 'DemoComponent',
// // vue2监视属性的写法 - 简写
// watch: {
// sum(newValue, oldValue) {
// console.log(newValue, oldValue);
// },
// msg(newValue, oldValue) {
// console.log(newValue, oldValue);
// }
// },
// // vue2监视属性的写法 - 完整
// watch: {
// sum: {
// immediate: true, // 立即生效
// handler(newValue, oldValue) {
// console.log(newValue, oldValue);
// },
// },
// msg: {
// immediate: true,
// handler(newValue, oldValue) {
// console.log(newValue, oldValue);
// }
// }
// },
setup() {
let sum = ref(0);
let msg = ref('你好啊')
let person = reactive({
name: '张三',
job: {
j1: {
salary: 20
}
}
})
// 情况一:监视ref所定义的一个响应式数据
// watch(sum, (newValue, oldValue) => {
// console.log(newValue, oldValue);
// }, {immediate: true})
// 情况二:监视ref所定义的多个响应式数据
// watch([sum, msg], (newValue, oldValue) => {
// console.log(newValue, oldValue);
// }, { immediate: true })
// 情况三:监视reactive所定义的一个响应式数据
/**
* 注意1:此处无法正确获取oldValue
* 注意2:强制开启了深度监视(配置deep无效)
*/
// watch(person, (newValue, oldValue) => {
// console.log(newValue, oldValue);
// }, {deep: false}) // 此处的deep无效
// 情况四:监视reactive所定义的一个响应式数据中的某个属性
// watch(() => person.name, (newValue, oldValue) => {
// console.log(newValue, oldValue);
// }, { immediate: true })
// 情况五:监视reactive所定义的一个响应式数据中的"某些"属性
// watch([() => person.name], (newValue, oldValue) => {
// // 多个用数组,[() => person.job, () => person.age]
// console.log(newValue, oldValue);
// }, {immediate: true})
// 特殊情况, 监听reactive内的某个对象属性,如果没开启深度监视deep,那么将无法监听到改变, 当然此处与情况三一样,此处无法正确获取oldValue
watch(() => person.job, (newValue, oldValue) => {
console.log(newValue, oldValue);
}, {immediate: true, deep: true})
return {
sum,
msg,
person
}
}
}
</script>
3. watch监听ref时value的问题
具体案例代码如下:
<template>
<div>{{ sum }}</div>
<button @click="sum++">sum按钮</button>
<div>{{ msg }}</div>
<button @click="msg += `!`">msg按钮</button>
<hr />
<div>{{ person.name }}</div>
<button @click="person.name += '~'">按钮name</button>
<div>{{ person.job.j1.salary }}</div>
<button @click="person.job.j1.salary++">按钮salary</button>
</template>
<script>
import { ref, watch } from 'vue'
export default {
name: 'DemoComponent',
setup() {
let sum = ref(0);
let msg = ref('你好啊')
let person = ref({
name: '张三',
job: {
j1: {
salary: 20
}
}
})
// 监听基本数据类型不需要.value,因为监听的是Impl对象,value发生改变就能监听到
// watch(sum, (newValue, oldValue) => {
// console.log(newValue, oldValue);
// }, {immediate: true})
// 监听对象类型时,如果这样写会监听不到salary改变,因为Impl对象的value是Proxy(reactive),内容改变时地址并未发生改变所以监听不到,有两种方案,下面演示
// watch(person, (newValue, oldValue) => {
// console.log(newValue, oldValue);
// }, {immediate: true})
// 第一种方案, 监听person.value,因为是reactive实现的,所以默认开启深度监视会监听到
// watch(person.value, (newValue, oldValue) => {
// console.log(newValue, oldValue);
// }, {immediate: true})
// 第二种方案, 开启深度监视会监听到, 这种方案更佳
watch(person, (newValue, oldValue) => {
console.log(newValue, oldValue);
}, { immediate: true, deep: true })
return {
sum,
msg,
person
}
}
}
</script>
4. watchEffect函数(与watch对比)
watchEffect函数(初始化页面就会触发一次)
1. watch的套路是:既要指明监视的属性,也要指明监视的回调
2. watchEffect的套路是:不用指明监视哪个属性,监视的回调中用到哪个属性,那就监视哪个属性
3. watchEffect有点像computed:
3.1 但computed注重的是计算出来的值(回调函数的返回值),所以必须要写返回值
3.2 而watchEffect更注重的是过程(回调函数的函数体),所以不用写返回值
具体案例代码如下:
<template>
<div>{{ sum }}</div>
<button @click="sum++">sum按钮</button>
<div>{{ msg }}</div>
<button @click="msg += `!`">msg按钮</button>
<hr />
<div>{{ person.name }}</div>
<button @click="person.name += '~'">按钮name</button>
<div>{{ person.job.j1.salary }}</div>
<button @click="person.job.j1.salary++">按钮salary</button>
</template>
<script>
import { reactive, ref, watchEffect } from 'vue'
export default {
name: 'DemoComponent',
setup() {
let sum = ref(0);
let msg = ref('你好啊')
let person = reactive({
name: '张三',
job: {
j1: {
salary: 20
}
}
})
// 用了谁就监视谁
watchEffect(() => {
const x1 = sum.value;
const x2 = person.job.j1.salary;
console.log('我触发了', x1, x2);
})
// watch监视写法, 与上方watchEffect作对比
// watch(person, (newValue, oldValue) => {
// console.log(newValue, oldValue);
// }, {})
return {
sum,
msg,
person
}
}
}
</script>