計算屬性與監視就是回調函數,`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>
```

**語法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>
```

<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>
```

**語法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>
```

<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>
```

- 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