本篇文章将介绍Vue3中的新增杀器 —— Composition API
: 一组低侵入式的、函数式的 API,它使我们能够更灵活地「组合」组件的逻辑。
Composition API
的灵感来自于 React Hooks
,是比 mixin
更强大的存在。它可以提高代码逻辑的可复用性,从而实现与模板的无关性;同时函数式的编程使代码的可压缩性更强。另外,把 Reactivity
模块独立开来,意味着 Vue3.0 的响应式模块可以与其他框架相组合。
如上图,在较大组件的编写中, Composition-Api
可以把复杂组件的逻辑抽地更紧凑,而且可以将公共逻辑进行抽取。
setup() 函数
在学习 Composition-Api
之前,我们需要先了解一下 setup()
函数。 setup()
是 Vue3 中的新增内容。它为基于 Composition API
的新特性提供了统一的入口。
在Vue3中,定义
methods
、watch
、computed
、data
数据 等都放在了setup()
函数中
1. 执行时机
setup()
函数会在created()
生命周期之前执行。
2. 接收props数据
setup()
函数的第一个参数是 props
,组件接收的 props
数据可以在 setup()
函数内访问到。
setup(props) {console.log(props.p1)
}
3. context上下文对象
context
是 setup()
的第二个参数,它是一个上下文对象,可以通过 context
来访问Vue的实例 this
。
setup(props,context) {console.log(this)console.log(context)
}
注意:在
setup()
函数中访问不到Vue的this
实例
Composition-Api
一组低侵入式的、函数式的 API,使得我们能够更灵活地「组合」组件的逻辑。
1. reactive()
reactive()
函数接收一个普通的对象,返回出一个响应式对象。
在Vue2.x的版本中,我们只需要在
data()
中定义一个数据就能将它变为响应式数据,在 Vue3.0 中,需要用reactive
函数或者ref
来创建响应式数据。
-
用reactive创建响应式对象
// 在组件库中引入 reactive import { reactive } from '@vue/ composition-api'setup() {// 创建响应式对象const state = reactive({count:0});// 将响应式对象return出去,暴露给模板使用return state; }
-
使用响应式对象
<p>当前的count的值为:{{count}}</p><button @click="count++">点击增加count< button>
2. ref()
ref()
函数可以根据给定的值来创建一个响应式的数据对象,返回值是一个对象,且只包含一个 .value
属性。
-
用 ref 创建响应式对象
// 引入 ref import { ref } from '@vue/composition-api'setup() {// 创建响应式对象const count = ref(0);return {count} }
-
使用响应式对象
<p>当前的count的值为:{{count}}</p><button @click="count++">点击增加count</button>
-
ref 的注意事项
-
在
setup()
函数内,由ref()
创建的响应式数据返回的是对象,所以需要用.value
来访问;而在
setup()
函数外部则不需要.value
,直接访问即可。 -
可以在
reactive
对象中访问ref()
函数创建的响应式数据。 -
新的
ref()
会覆盖旧的ref()
。
-
-
选择 reactive 还是 ref
Vue3 —— 创建响应式数据使用 reactive 还是 ref ?(本周更新)
3. computed()
computed()
用来创建计算属性,返回值是一个 ref()
实例。按照惯例,使用前需要先引入。
-
computed创建只读计算属性
给
computed()
传入一个函数,可以得到一个只读的计算属性:const count = ref(1)// 创建一个计算属性,使其值比 count 大 1 const bigCount = computed(() => count.value + 1)console.log(bigCount.value) // 输出 2 bigCount.value++ // error 不可写
-
computed创建可读可写计算属性
const count = ref(1)// 创建一个 computed 计算属性,传入一个对象 const bigCount = computed({// 取值函数get: () => (count.value + 1),// 赋值函数set: val => {count.value = val - 1} })// 给计算属性赋值的操作,会触发 set 函数 bigCount.value = 9 // 触发 set 函数后,count 的值会被更新 console.log(count.value) // 8
4. readonly()
传入一个响应式对象、普通对象或 ref ,返回一个只读的对象代理。这个代理是深层次的,对象内部的数据也是只读的。
const state = reactive({ count: 0 })const copy = readonly(state)watchEffect(() => {// 依赖追踪console.log(copy.count)
})// state 上的修改会触发 copy 上的侦听
state.count++// 这里只读属性不能被修改
copy.count++ // warning!
5. watchEffect()
watchEffect()
会立即执行传入的函数,并响应式侦听其依赖,并在其依赖变更时重新运行该函数。
-
基本用法
const count = ref(0)// 初次直接执行,打印出 0 watchEffect(() => console.log(count.value))setTimeout(() => {// 被侦听的数据发生变化,触发函数打印出 1count.value++ }, 1000)
-
停止侦听
watchEffect()
使用时返回一个函数,当执行这个返回的函数时,就停止侦听。const stop = watchEffect(() => {/* ... */ })// 停止侦听 stop()
-
更多功能
请参照 composition-api 文档 —— watchEffect
6. watch()
composition-api
中的 watch
和 Vue2.x 中是一样的,watch
需要侦听数据,并执行它的侦听回调。默认情况下初次渲染不执行。
-
watch
与watchEffect
的不同watch
初次渲染不执行watch
侦听的更具体watch
可以访问侦听数据变化前后的值
-
watch
侦听单个数据源侦听的数据可以是个
reactive
创建出的响应式数据(拥有返回值的 getter 函数),也可以是个ref
// 侦听一个 getter const state = reactive({ count: 0 }) watch(() => state.count,(count, prevCount) => {/* ... */} )// 直接侦听一个 ref const count = ref(0) watch(count, (count, prevCount) => {/* ... */ })
-
watch
侦听多个数据源在侦听多个数据源时,把参数以数组的形式给
watch
watch([ref1, ref2], ([newRef1, newRef2], [prevRef1, prevRef2]) => {/* ... */ })
-
与
watchEffect
同样的更多功能请参照 composition-api 文档 —— watch
Composition-Api 依赖工具
下面介绍一下组合式API的依赖方法集:
1. isRef()
isRef()
顾名思义,是用来判断某个值是否为 ref()
创建出来的响应式的值。
当你需要展开某个可能为 ref()
创建的响应式的值的时候,会用到它:
import { isRef } from '@vue/composition-api'const unwrapper = isRef(foo) ? foo.value : foo
2. toRefs()
toRefs()
可以将 reactive()
创建出来的响应式对象转换成内容为 ref 响应式的值的普通对象
在搞清楚
toRefs()
的用法之前,我们需要先了解一下用reactive()
和ref()
创建出来的响应式对象的区别:
- 用
reactive()
创建的响应式对象,整个对象是响应式的,而对象里的每一项都是普通的值。当你把它用展开运算符展开后,整个对象的普通值都不是响应式的;- 而用
ref()
创建的响应式的值,本身就是响应式的,并不依赖于其他对象。
所以当你需要展开 reactive()
创建的响应式对象,又不想让他们失去响应式特点的时候,就需要用 toRefs()
将它进行转换:
import { toRefs } from '@vue/composition-api'setup() {// 定义响应式数据对象const state = reactive({count: 0})// 定义简单的函数,使count每次+1const add = () => {state.count++}// 将setup函数的内容return出去,供外界使用return {// 将 state 展开导出,同时将其属性都转化为 ref 形式的响应式数据...toRefs(state),add}
}
<template><div><p>当前的count值为:{{count}}</p><button @click="add">点击+1</button></div>
</template>
其他方法
请参照 composition-api 文档 —— 响应式系统工具集
相关链接
- Vue3 的新特性