提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
文章目录
- 前言
- 一、Composition Api是什么?
- 二、使用步骤
-
- 1.写在哪
- setup其实是组件的另外一个选项:
- 2.函数的使用
- 既然是一个函数,那么可以有返回值,作用可以理解为替代data选项
- 甚至是我们可以返回一个执行函数来代替在methods中定义的方法:
- 如果我们将 counter 在 increment 或者 decrement进行操作时,是否可以实现界面的响应式呢?
- reactive函数
-
- ref
-
- ref自动解包
- readonly
- 在开发中常见的readonly方法会传入三个类型的参数
- readonly的使用
- Reactive判断的API
- toRefs
- toRef
- ref其他的API
- setup不可以使用this
前言
一、Composition Api是什么?
- 在vue2中,编写组件的方式都是一个一个固定的
选项(options)
,例如,data定义数据
、methods中定义方法
、computed中定义计算属性
、watch中监听属性改变(也包括生命周期钩子)
、
- 随着项目的
不断迭代
,也就意味着功能越来越多,当组件变得更大
、更复杂
时、逻辑关注点的列表就会增长
、同一个功能的逻辑就会被拆分的很分散
; 后期迭代开发会更挠头
- 如果能将同一个
逻辑关注点相关的代码
放在一起
那么开发不就更清晰了吗
vue3新提出的概念,Composition Api 就是为了解决这个问题
二、使用步骤
1.写在哪
- 我们需要一个可以实际使用它的地方
- 在Vue组件中,
setup函数
setup其实是组件的另外一个选项:
- 只不过这个选项强大到我们可以
用它来替代之前所编写的大部分其他选项
- 比如
methods
、computed
、watch
、data
、生命周期
等等
2.函数的使用
既然是一个函数,那么可以有返回值,作用可以理解为替代data选项
注意:必须返回 模板中才能渲染
甚至是我们可以返回一个执行函数来代替在methods中定义的方法:
setup(){
let message = "message";
let counter = 100;
const increment = ()=>{
counter++;
}
const decrement = ()=>{
counter--;
}
return{message,counter,increment,decrement} ;
}
如果我们将 counter 在 increment 或者 decrement进行操作时,是否可以实现界面的响应式呢?
- 不是响应式
- 因为对于默认定义的变量,默认情况下,Vue并不会跟踪它 的变化,也不会引起界面的响应式变化。
reactive函数
- vue提供了api,用来响应式定义复杂数据,
- reactive({})
- 注意:对传入的类型是有限制的,要求必须传入一个对象或者数组。
为什么它定义的数据就变成响应式的呢?
- 因为当我们使用reactive函数 处理我们的数据之后,数据
再次被使用
时就会进行依赖收集
- 当数据
发生改变
时,所有收集到的依赖
都是进行对应的响应式
操作(比如更新界面)
- 选项式api,data选项,也是
内部
交给了某一个函数将其变成响应式对象的。
ref
- vue提供用来定义响应式基本类型的api
- 会返回一个
可变的响应式对象
,该对象作为一个响应式的引用
维护着它内部的值
,这也是名称的由来。
- 它内部的值是在
ref的 value 属性
中被维护的;
const message = ref("信息")
- 注意:
- 在
模板中引入ref
的值时,Vue会自动帮助我们进行解包
操作,所以我们并不需要在模板中通过 ref.value 的方式来使用;
- 但是在
setup 函数内部
,它依然是一个 ref引用
, 所以对其进行操作时,我们依然需要使用 ref.value
的方式;
ref自动解包
模板中的解包是浅层的解包
- 如果我们将
ref放到一个reactive的属性
当中,那么在模板中使用时,它会自动解包
readonly
- 背景:
reactive或者ref可以获取到一个响应式的对象
,但是某些情况下,我们传入
给其他地方(组件)的这个响应式对象希望在另外一个地方(组件)被使用,但是不能被修改
,这个时候如何防止这种情况的出现
- 提供了
readonly
的方法
- readonly会
返回
原始对象的只读代理
(也就是它依然是一个Proxy,这是一个proxy的set
方法被劫持,并且不能对其进行修
改)
在开发中常见的readonly方法会传入三个类型的参数
- 类型一:
普通对象
- 类型二:reactive返回的对象
- 类型三:ref的对象
readonly的使用
- 在readonly的使用过程中,有如下规则
- readonly返回的对象都是
不允许修改
的
- 但是经过readonly处理的
原来的对象
是允许
被修改的
- 比如 const info = readonly(obj),info对象是不允许被修改的
- 当obj被修改时,readonly返回的info对象也会被修改
- 但是我们不能去修改readonly返回的对象info
- 本质上就是
readonly返回的对象的setter方法
被劫持了
Reactive判断的API
- isProxy
- 检查对象
是否
是由 reactive 或 readonly创建的 proxy
- isReactive
- 检查对象是否是由 reactive创建的响应式代理
- isReadonly
- 检查对象是否是由 readonly 创建的只读代理
- toRaw
- 返回 reactive 或 readonly 代理的原始对象(不建议保留对原始对象的持久引用。请谨慎使用)
- shallowReactive
- 创建一个响应式代理,它跟踪其自身 property 的响应性,但不执行嵌套对象的深层响应式转换 (深层还是原生对象)
- shallowReadonly
- 创建一个 proxy,使其自身的 property 为只读,但不执行嵌套对象的深度只读转换(深层还是可读、可写的)
toRefs
- 如果我们使用ES6的
解构语法
,对reactive返回的对象进行解构获取值
,那么之后无论是修改
解构后的变量,还是修改reactive
返回的state对象,数据都不再是响应式
的
const state = reactive({
message:'信息',
age:20
});
const { message,age } = state
- 那么有没有办法让我们解构出来的属性是响应式的呢
- 提供了一个
toRefs的函数
,可以将reactive返回的对象中的属性都转成ref
- 那么我们再次进行结构出来的 message和 age 本身都是 ref的
const { message,age } = toRefs(state)
- 相当于已经在state.name和ref.value之间建立了 链接,任何一个修改都会引起另外一个变化
toRef
- 如果我们只希望转换一个reactive对象中的属性为ref, 那么可以使用toRef的方法
const name = toRef(state,'name');
const {age} = state;
const addName = ()=>{
state.name = 'dfh'
}
ref其他的API
- unref
- 如果我们想要获取一个ref引用中的value,那么也可以通过unref方法
- 如果参数是一个 ref,则返回内部值,否则返回参数本身
- isRef
- 判断值是否是一个ref对象
- shallowRef
- 创建一个浅层的ref对象
- triggerRef
- 手动触发和 shallowRef 相关联的副作用
setup不可以使用this
- this并没有指向当前组件实例
- 并且在setup被调用之前,data、computed、methods等都没有被解析
- 所以无法在setup中获取this