前言
本文主要介紹 vue3 新增 Composition API 的一些特性 setup()、computed()和 watch(),Composition API 可以把復雜組件的邏輯變得更為緊湊,使代碼有更高復用性和靈活性。
1. setup()
setup()是 vue3 中新增特性,在組件 created()生命周期之前執行。
因為 setup() 是在組件 created()之前執行的,所以在 setup()內部無法獲取 this。
setup(props,context)接收兩個參數:props,context
參數一:props
組件接收的 props 數據可以在 setup()函數內訪問到。
export default {
props: {
title: String
},
setup(props) {
console.log(props.title)
}
}
props 具有響應性,不能使用 ES6 解構它,這會使其失去響應性。如果需要解構,可以使用 toRefs()
const { title } = toRefs(props)
console.log(title.value)
如果 title 是一個可選的屬性,需使用 toRef(),如下:
import { toRef } from 'vue'
setup(props) {
const title = toRef(props, 'title')
console.log(title.value)
}
參數二:context:
`context` 是一個上下文對象,可以通過 context 來訪問 Vue 的實力 this。
`context` 內部包括三個屬性:`attrs`、`slots`、`emit`
export default {
setup(props, { attrs, slots, emit }) {
// ...
}
}
context 是一個常規的 js 對象,它不具有響應性可以直接對它解構。但 attrs 和 slots 是有狀態的對象,當組件本身更新時它們也會隨之更新,這意味着我們應該避免解構它們。
2. computed()
computed()創建只讀計算屬性
const count = ref(1)
// 創建一個只讀性計算屬性,依賴於count值
const plusOne = computed(() => count.value + 1)
console.log(plusOne.value) // 2
plusOne.value++ // error 該計算屬性為只讀屬性,不可寫
computed()創建可讀寫計算屬性
const count = ref(1)
// 創建一個可讀寫計算屬性
const plusOne = computed({
get: () => count.value + 1,
set: (val) => {
count.value = val - 1
}
})
plusOne.value = 1
console.log(count.value) // 0
3. watch()
watch()監聽單個數據源
// 監聽 a getter
const state = reactive({ count: 0 })
watch(
() => state.count,
(count, prevCount) => {
/* ... */
}
)
// 直接監聽 a ref
const count = ref(0)
watch(count, (count, prevCount) => {
/* ... */
})
watch()監聽多個數據源
第一個參數中,要監聽的數據源以數組的形式傳入。
const firstName = ref('')
const lastName = ref('')
watch([firstName, lastName], (newValues, prevValues) => {
console.log(newValues, prevValues)
})
firstName.value = 'John' // logs: ["John",""] ["", ""]
lastName.value = 'Smith' // logs: ["John", "Smith"] ["John", ""]
另,當監聽一個響應性對象時,
const numbers = reactive([1, 2, 3, 4])
watch(
() => [...numbers],
(numbers, prevNumbers) => {
console.log(numbers, prevNumbers)
}
)
numbers.push(5) // logs: [1,2,3,4,5] [1,2,3,4]
當監聽一個復雜對象的屬性或者數組時需要傳入第三個參數{deep:true},如下:
const state = reactive({
id: 1,
attributes: {
name: ''
}
})
watch(
() => state,
(state, prevState) => {
console.log('not deep ', state.attributes.name, prevState.attributes.name)
}
)
watch(
() => state,
(state, prevState) => {
console.log('deep ', state.attributes.name, prevState.attributes.name)
},
{ deep: true }
)
state.attributes.name = 'Alex' // Logs: "deep " "Alex" "Alex"
監聽一個響應式對象或者數組時總是返回當前數據變化前后的引用,為了真正的監聽復雜對象或數組,需要進行一次深拷貝。
官方推薦方案:lodash.cloneDeep
import _ from 'lodash'
const state = reactive({
id: 1,
attributes: {
name: 'lemon'
}
})
watch(
() => _.cloneDeep(state),
(state, prevState) => {
console.log(state.attributes.name, prevState.attributes.name)
}
)
state.attributes.name = 'Alex' // Logs: "Alex" "lemon"
更多詳細用法請參考Composition API——watch
