计算属性与监视就是回调函数,`computed`是计算属性函数、`watch`/`watchEffect`是监视函数,它们都可以监控一个数据的变化,当这个数据发送变化后进行相应的后续处理。
[TOC]
# 1. `computed`计算属性
**1. 调用语法**
```js
/* 语法1 */
//当只传入一个回调函数时,该回调函数默认为get函数
//当targetValue发送变化时,computed能够监视到数据的变化,并将变化后的值返回
//computed函数返回一个ComputedRef对象,是一个响应式的对象
const returnVal = computed(() => {
return targetValue
})
/* 语法2 */
//当需要get与set函数时,应该传入一个对象
//当returnVal发送改变时,val就是returnVal改变后的值
const returnVal = computed({
get() { return targetValue }
set(val) { targetValue = val }
})
```
**语法1:演示示例**
```html
<template>
<fieldset>
<legend>改变数据</legend>
<!-- 4. 在这里让user.firstName发生改变 -->
firstName: <input type="text" placeholder="firstName" autocomplete="off" v-model="user.firstName" /><br />
lastName: <input type="text" placeholder="lastName" autocomplete="off" v-model="user.lastName" />
</fieldset>
<fieldset>
<legend>改变数据后的数据</legend>
<!-- 5. 在这里展示发生变化后的数据 -->
<input type="text" placeholder="fullName1" autocomplete="off" v-model="fullName1" />
</fieldset>
</template>
<script lang="ts">
//1. 引入计算属性与监视
import { computed, defineComponent, reactive, ref, watch, watchEffect } from 'vue'
export default defineComponent({
setup() {
//2. 定义了一个响应式的对象
const user = reactive({
firstName: '东方',
lastName: '不败'
})
//3. 只监视user.firstName属性,当user.firstName属性值发生变化后,返回它变化后的值
//只监视user.firstName属性,所以user.lastName发生变化时不会被执行
const fullName1 = computed(() => {
return user.firstName
})
return {
user,
fullName1,
}
}
})
</script>
```
![](https://img.kancloud.cn/28/28/2828aac1e4124352f8dc299091ee2281_1262x211.gif)
**语法2:演示示例**
```html
<template>
<fieldset>
<legend>改变数据</legend>
<!-- 4. 在这里让user.firstName发生改变 -->
firstName: <input type="text" placeholder="firstName" autocomplete="off" v-model="user.firstName" /><br />
lastName: <input type="text" placeholder="lastName" autocomplete="off" v-model="user.lastName" />
</fieldset>
<fieldset>
<legend>改变数据后的数据</legend>
<!-- 5. 在这里让fullName2.value发生改变 -->
<input type="text" placeholder="fullName2" autocomplete="off" v-model="fullName2" />
</fieldset>
</template>
<script lang="ts">
//1. 引入计算属性与监视
import { computed, defineComponent, reactive, ref, watch, watchEffect } from 'vue'
export default defineComponent({
setup() {
//2. 定义了一个响应式的对象
const user = reactive({
firstName: '东方',
lastName: '不败'
})
//3. 只监视user.firstName属性
const fullName2 = computed({
//当user.firstName属性值发生变化后,返回它变化后的值
get() {
return user.firstName
},
//当fullName2发生变化后,获取发生变化后的数据并赋值给user.firstName
set(val: string) {
user.firstName = val
}
})
return {
user,
fullName2,
}
}
})
</script>
</script>
```
![](https://img.kancloud.cn/6c/6d/6c6d766f0443cd8e2751ed48a39d9250_1262x211.gif)
<br/>
# 2. `watch`监视
**1. 调用语法**
```js
/* 语法1:只监视一个数据 */
//data:被监视的数据
//(val) => {}:当data发生变化时该回调函数就会被调用
//val:就是data发生变化后的新数据
//immediate:true则默认自动执行一次,因为当obj发生变化时回调才会被调用,newObj才有值,
// 但是首次初始化obj时obj并没有发生变化,newObj就是一个空对象。
//deep:true则进行深度监视,即obj可能有多层嵌套,每一层都会被监视;false则只监视obj对象的第一层
watch(data, (val) => {}, {immediate: true, deep: true})
//如果data是一个对象{lastName: '', firstName: ''},也可以如下写
watch(data, ({lastName, firstName}) => {}, {immediate: true, deep: true})
/* 语法2:监视多个数据 */
//当 obj.val1 不是响应式数据时,需要以 ()=>obj.val1 声明才能被监视到
//vals是一个数组,顺序就是 [()=>obj.val1, ()=>obj.val2] 的顺序
watch([()=>obj.val1, ()=>obj.val2], (vals) => {})
```
**语法1:只监视一个数据演示示例**
```html
<template>
<fieldset>
<legend>改变数据</legend>
<!-- 5. 在这里让user发生改变 -->
firstName: <input type="text" placeholder="firstName" autocomplete="off" v-model="user.firstName" /><br />
lastName: <input type="text" placeholder="lastName" autocomplete="off" v-model="user.lastName" />
</fieldset>
<fieldset>
<legend>改变数据后的数据</legend>
<!-- 6. 在这里让fullName3.value发生改变 -->
<input type="text" placeholder="fullName3" autocomplete="off" v-model="fullName3" />
</fieldset>
</template>
<script lang="ts">
//1. 引入计算属性与监视
import { computed, defineComponent, reactive, ref, watch, watchEffect } from 'vue'
export default defineComponent({
setup() {
//2. 定义了一个响应式的对象
const user = reactive({
firstName: '东方',
lastName: '不败'
})
const fullName3 = ref('')
//3. 监视user对象,当user任何一个属性发生变化时都会被执行
//虽然我在这里只写了一个firstName,但是改变lastName时回调也会被执行
//当user任何一个属性发生变化时将变化后的firstName赋值给fullName3.value
watch(user, ({ firstName }) => {
fullName3.value = firstName
}, { immediate: true, deep: true })
//4. 监视fullName3,val就是发生改变后的fullName3.value
watch(fullName3, (val) => {
user.firstName = val
})
return {
user,
fullName3,
}
}
})
</script>
```
![](https://img.kancloud.cn/81/5b/815b8601b40267a7efa104b4f73cabad_1262x205.gif)
**语法2:监视多个数据演示示例**
```html
<template>
<fieldset>
<legend>改变数据</legend>
<!-- 4. 在这里让user发生改变 -->
firstName: <input type="text" placeholder="firstName" autocomplete="off" v-model="user.firstName" /><br />
lastName: <input type="text" placeholder="lastName" autocomplete="off" v-model="user.lastName" />
</fieldset>
<fieldset>
<legend>改变数据后的数据</legend>
<!-- 5. 在这里让fullName4.value发生改变 -->
<input type="text" placeholder="fullName4" autocomplete="off" v-model="fullName4" />
</fieldset>
</template>
<script lang="ts">
//1. 引入计算属性与监视
import { computed, defineComponent, reactive, ref, watch, watchEffect } from 'vue'
export default defineComponent({
setup() {
//2. 定义了一个响应式的对象
const user = reactive({
firstName: '东方',
lastName: '不败'
})
const fullName4 = ref(1)
//3. 监视user.firstName、user.lastName、fullName4
//虽然user是响应式数据,但是user.firstName、user.lastName不是是响应式数据需要以 () => user.firstName 被监听
//fullName4本身就是一个响应式数据,直接放到数组中即可
watch([() => user.firstName, () => user.lastName, fullName4], (vals) => {
console.log(vals)
}, { immediate: true, deep: true })
return {
user,
fullName4,
}
}
})
</script>
```
![](https://img.kancloud.cn/db/07/db0721cc6aff6f41f347e399674729f3_1262x434.gif)
<br/>
# 3. `watchEffect`监视
`watchEffect`与`watch`的区别是:`watchEffect`不需要配置`{ immediate: true, deep: true }`,默认初始化时就执行一次并可以深层监视。
**1. 调用语法**
```js
//直接将targetObj放入回调函数就可以监视targetObj对象的变化了
watchEffect(() => { targetObj })
```
**2. 演示示例**
```html
<template>
<fieldset>
<legend>改变数据</legend>
<!-- 5. 在这里让user.firstName发生改变 -->
firstName: <input type="text" placeholder="firstName" autocomplete="off" v-model="user.firstName"/><br/>
lastName: <input type="text" placeholder="lastName" autocomplete="off" v-model="user.lastName"/>
</fieldset><fieldset>
<legend>改变数据后的数据</legend>
<!-- 6. 在这里让fullName5.value发生改变 -->
<input type="text" placeholder="fullName5" autocomplete="off" v-model="fullName5"/>
</fieldset>
</template>
<script lang="ts">
//1. 引入计算属性与监视
import { computed, defineComponent, reactive, ref, watch, watchEffect } from 'vue'
export default defineComponent({
setup() {
//2. 定义了一个响应式的对象
const user = reactive({
firstName: '东方',
lastName: '不败'
})
const fullName5 = ref('')
//3. 监视user.firstName属性,当user.firstName值发生变化时则将它变化后的值赋值给fullName5.value
//这里只监视user.firstName属性,如果user没有被监视的属性也发生变化不会被调用
watchEffect(() => {
fullName5.value = user.firstName
})
//4. 监视fullName5.value,当fullName5.value发生变化时则将变化后的值赋值给user.firstName
watchEffect(() => {
user.firstName = fullName5.value
})
return {
user,
fullName5
}
}
})
</script>
```
![](https://img.kancloud.cn/6b/32/6b324aa0a0b2ad973253a87ef6422640_1262x211.gif)
- nodejs
- 同时安装多个node版本
- Vue3
- 创建Vue3项目
- 使用 vue-cli 创建
- 使用 vite 创建
- 常用的Composition API
- setup
- ref
- reactive
- 响应数据原理
- setup细节
- reactive与ref细节
- 计算属性与监视
- 生命周期函数
- toRefs
- 其它的Composition API
- shallowReactive与shallowRef
- readonly与shallowReadonly
- toRaw与markRaw
- toRef
- customRef
- provide与inject
- 响应式数据的判断
- 组件
- Fragment片断
- Teleport瞬移
- Suspense
- ES6
- Promise对象
- Promise作用
- 状态与过程
- 基本使用
- 常用API
- async与await
- Axios