Vue3的新特性(三):setup()、computed()和watch()

前言

本文主要介绍 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()函数内访问到。

1
2
3
4
5
6
7
8
export default {
props: {
title: String
},
setup(props) {
console.log(props.title)
}
}

props 具有响应性,不能使用 ES6 解构它,这会使其失去响应性。如果需要解构,可以使用 toRefs()

1
2
const { title } = toRefs(props)
console.log(title.value)

如果 title 是一个可选的属性,需使用 toRef(),如下:

1
2
3
4
5
import { toRef } from 'vue'
setup(props) {
const title = toRef(props, 'title')
console.log(title.value)
}
参数二:context:
`context` 是一个上下文对象,可以通过 context 来访问 Vue 的实力 this。
`context` 内部包括三个属性:`attrs`、`slots`、`emit`
1
2
3
4
5
export default {
setup(props, { attrs, slots, emit }) {
// ...
}
}

context 是一个常规的 js 对象,它不具有响应性可以直接对它解构。但 attrsslots 是有状态的对象,当组件本身更新时它们也会随之更新,这意味着我们应该避免解构它们。

2. computed()

computed()创建只读计算属性
1
2
3
4
5
const count = ref(1)
// 创建一个只读性计算属性,依赖于count值
const plusOne = computed(() => count.value + 1)
console.log(plusOne.value) // 2
plusOne.value++ // error 该计算属性为只读属性,不可写
computed()创建可读写计算属性
1
2
3
4
5
6
7
8
9
10
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()监听单个数据源
1
2
3
4
5
6
7
8
9
10
11
12
13
14
// 监听 a getter
const state = reactive({ count: 0 })
watch(
() => state.count,
(count, prevCount) => {
/* ... */
}
)

// 直接监听 a ref
const count = ref(0)
watch(count, (count, prevCount) => {
/* ... */
})
watch()监听多个数据源

第一个参数中,要监听的数据源以数组的形式传入。

1
2
3
4
5
6
7
8
9
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", ""]

另,当监听一个响应性对象时,

1
2
3
4
5
6
7
8
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},如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
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

打赏
  • 版权声明: 本博客所有文章除特别声明外,著作权归作者所有。转载请注明出处!
  • Copyrights © 2015-2022 Lillian
  • 访问人数: | 浏览次数:

请我喝杯咖啡吧~

支付宝
微信