[TOC]
参考文档:https://juejin.cn/post/7005140118960865317/#heading-26
1. computed
import { computed } from 'vue'
const 计算属性名 = computed(() => {
return 响应式数据相关计算
})
1.1 简写
<template>
<div>
<h2>姓:{{person.firstName}}</h2>
<h2>名:{{person.lastName}}</h2>
<h2>全名:{{fullName}}</h2>
</div>
</template>
<script>
import { computed, reactive} from'vue'
export default {
setup() {
const person = reactive({
firstName:'张',
lastName:'三'
})
const fullName = computed(() => {
return person.firstName +'-'+ person.lastName
})
return { person ,fullName}
},
}
</script>
1.2 高级用法
const fullName = computed({
get() {
return person.firstName + '-' + person.lastName
},
set(value) {
const nameArr = value.split('-')
person.firstName = nameArr[0]
person.lastName = nameArr[1]
},
})
1.3 computed传参
<template>
<div>
<h3>count:{{getCountByParams(10,20)}}</h3>
</div>
</template>
<script>
import { computed, reactive } from 'vue'
export default {
setup() {
const getCountByParams = computed(() => (a,b) => {
return a*b
})
return { getCountByParams }
},
}
</script>
2. watch
:::success
watch(person, (newValue, oldValue) => {
console.log(newValue, oldValue)
},{deep: true}, {immediate: true})
:::
2.1 监听ref定义的响应式数据
<template>
<div>
<h3>count:{{count}}</h3>
<button @click="add">add</button>
</div>
</template>
<script>
import { ref, watch } from 'vue'
export default {
setup() {
const count = ref(0)
function add() {
count.value++
}
watch(count, (newValue, oldValue) => {
console.log(newValue, oldValue)
})
return { count, add, }
},
}
</script>
此处监听是, 只能写count, 不能写count.value。因为, 如果写count.value, 那么次数相当于监听的是0。 此时真正监听的RefImpl这个对象。
2.2 监听多个ref定义的响应式数据
<template>
<div>
<h3>count:{{count}}</h3>
<h3>sum:{{sum}}</h3>
<button @click="add">add</button>
</div>
</template>
<script>
import { ref, watch } from 'vue'
export default {
setup() {
let count = ref(10)
let sum = ref(20)
function add() {
count.value++
sum.value *= 10
}
watch([count, sum], (newValue, oldValue) => {
console.log(newValue, oldValue) //[12, 2000] (2) [11, 200]
/*
newValue时一个数组:包含count和sum的变化后的值
oldValue时一个数组:包含count和sum的变化前的值
*/
} ,{immediate:true})
return { count,sum, add, }
},
}
2.3 监听reactive定义的响应式数据
如果监听用reactive定义的响应式数据, 此处无法正确的监听oldValue。
<template>
<div>
<h2>姓名:{{person.name}}</h2>
<h2>年龄:{{person.age}}</h2>
<button @click="person.name +='@'">修改姓名</button>
<button @click="person.age ++">修改年龄</button>
</div>
</template>
<script>
import { reactive, watch } from 'vue'
export default {
setup() {
const person = reactive({
name: '张三',
age: 20,
})
watch(person, (newValue, oldValue) => {
console.log(newValue, oldValue)
})
return { person }
},
}
</script>
如果直接把reactive换成ref,用watch监听, 则监听不到变化。
<script>
import { reactive, watch ,ref} from 'vue'
export default {
setup() {
const person = ref({
name: '张三',
age: 20,
})
watch(person, (newValue, oldValue) => {
console.log(newValue, oldValue)
})
return { person }
},
}
</script>
如果打开深度监听,则可以监听到oldValue
import { reactive, watch ,ref} from 'vue'
export default {
setup() {
const person = ref({
name: '张三',
age: 20,
})
console.log(person)
watch(person, (newValue, oldValue) => {
console.log(newValue, oldValue)
},{deep: true})
return { person }
},
}
</script>
如果换成监听ref对应的value值, 则出现和reactive一样的问题, 还是监听不到oldValue。因为用ref定义的引用类型的响应式数据, 它的底层还是借助于reactive实现的。
import { reactive, watch ,ref} from 'vue'
export default {
setup() {
const person = ref({
name: '张三',
age: 20,
})
console.log(person)
watch(person.value, (newValue, oldValue) => {
console.log(newValue, oldValue)
})
return { person }
},
}
</script>
为啥这里可以写person.value。 因为此时的person.value对应的值是一个proxy。
2.4 监视整个对象
- 若watch监视的是reactive定义的响应式数据,则强制开启了深度监视
```javascriptwatch(person,(newValue,oldValue)=>{ console.log('person变化了',newValue,oldValue) },{immediate:true,deep:false}) //此处的deep配置不再奏效
姓名:{{person.name}}
年龄:{{person.age}}
薪资:{{person.job.salery}}K
监视**age**属性,可以正确拿到**oldValue**值 ```javascript
![image.png](https://cdn.nlark.com/yuque/0/2022/png/27402074/1658802464086-952072c1-f326-4a01-906a-1647650d079b.png#clientId=uf629d92c-60d7-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=351&id=ub6109939&margin=%5Bobject%20Object%5D&name=image.png&originHeight=526&originWidth=1228&originalType=binary&ratio=1&rotation=0&showTitle=false&size=52283&status=done&style=none&taskId=u22b14a7e-d9af-43a7-ab30-3ad67170229&title=&width=818.6666666666666)<br />监听多个属性, 放在**[]**中, 可以拿到正确的**oldValue**
```javascript
<script>
import { reactive, watch ,ref} from 'vue'
export default {
setup() {
const person = reactive({
name: '张三',
age: 20,
job:{
salery:20
}
})
watch([() => person.age, () => person.name], (newValue, oldValue) => {
console.log(newValue, oldValue)
})
return { person }
},
}
</script>
如果person对象的属性值为一个对象, 则需要开启深度监视:
<script>
import { reactive, watch ,ref} from 'vue'
export default {
setup() {
const person = reactive({
name: '张三',
age: 20,
job:{
salery:20
}
})
watch(() => person.job, (newValue, oldValue) => {
console.log(newValue, oldValue)
},{deep: true})
return { person }
},
}
</script>
- watch的套路是:既要指明监视的属性,也要指明监视的回调。
- watchEffect的套路是:不用指明监视哪个属性,监视的回调中用到哪个属性,那就监视哪个属性。
- watchEffect有点像computed:
- 但computed注重的计算出来的值(回调函数的返回值),所以必须要写返回值。
- 而watchEffect更注重的是过程(回调函数的函数体),所以不用写返回值。
- 默认开启了immediate: true,首次就会执行一次。
watchEffect所指定的回调中用到的数据只要发生变化,则直接重新执行回调。
<script>
import { reactive, watch ,ref, watchEffect} from 'vue'
export default {
setup() {
const person = reactive({
name: '张三',
age: 20,
})
console.log(person)
watchEffect(() => {
const m = person.name;
const n = person.age;
console.log('我执行了')
})
return { person }
},
}
</script>