Vue3.0深入浅出系列之Composition API

前言

最近公司正式将Vue3.0作为前端框架,自己也参与了2个Vue3.0项目的开发,所以准备出一个Vue3.0的学习系列,提到Vue3.0,就不得不说composition API,所以本文就作为Vue3.0系列的开篇之作。

image.png

解决什么痛点?

使用过Vue2.0通常知道,用(data、computed、methods、watch)组件选项来组织逻辑很有效,然而,随着组件变大,逻辑复制时,导致组件难以阅读合理解和后续维护性非常复杂,特别是接手别人代码时,往往需要来回跳转阅读。基于此composition api应用而生。对比图如下:

对比.png

setup

新的setup选项在组件创建之前执行,一旦props被解析,就将作为Composition API的入口。

setup中避免使用this,因为无法获取组件实例;同理,setup的调用发生在data、property、computed property、methods被解析之前,同样在setup中无法获取。

setup接收两个参数:

  • props (props是响应式的,不能使用ES6解构,如需解构使用toRefstoRef
  • context (普通对象,可解构,包含3个属性。context.attrs、context.slots、context.emit
import { toRefs,roRef } from 'vue'
props: {
  name: String,
  age: Number
},
setup(props,context){
  console.log(props.name)
  
  //toRefs 不会创建一个 ref ,而toRef 可以:
  const {name}=toRefs(props)
  const {age}=toRef(props,'age')
  
  
  // Attribute (非响应式对象)
  console.log(context.attrs)

  // 插槽 (非响应式对象)
  console.log(context.slots)

  // 触发事件 (方法)
  console.log(context.emit)
}
复制代码

结论

执行 setup 时,组件实例尚未被创建。因此,你只能访问以下 property:

  • props
  • attrs
  • slots
  • emit

换句话说,你将无法访问以下组件选项:

  • data
  • computed
  • methods

ref 与 reactive

在vue3中,官方提供了ref()reactive()两种方式声明响应式数据,接下来我们将详细介绍各自的用法以及两者的区别。

ref函数

接受一个内部值并返回一个响应式且可变的 ref 对象。ref 对象具有指向内部值的单个 property .value

import { ref } from 'vue'

const age = ref(0)
console.log(age.value) // 0

age.value++
console.log(age.value) // 1
复制代码

而为何将值封装到一个对象里面?

官方给出了分析和解释:

在 JavaScript 中,Number 或 String 等基本类型是通过值而非引用传递的。封装成对象,这样我们就可以在整个应用中安全地传递它,而不必担心在某个地方失去它的响应性。

gif

结论

ref 为我们的值创建了一个响应式引用

reactive函数

返回对象的响应式副本,响应式转换是“深层”的——它影响所有嵌套 property。

import { reactive } from 'vue'

const obj=reactive({
   name:'Vue3',
   age:1
})
复制代码

reactive 将解包所有深层的 refs,同时维持 ref 的响应性。

const age = ref(1)
const obj = reactive({ age })

// ref 会被解包
console.log(obj.age === age.value) // true

// 它会更新obj.age
age.value++
console.log(age.value) // 2
console.log(obj.age) // 2

// 它也会更新 age  ref
obj.age++
console.log(obj.age) // 3
console.log(age.value) // 3
复制代码

当将 ref 分配给 reactive property 时,ref 将被自动解包。

const age = ref(1)
const obj = reactive({})

obj.age = age

console.log(obj.age) // 1
console.log(obj.age === age.value) // true
复制代码

区别

reactive 和 ref 都是用来定义响应式数据的 reactive更推荐去定义复杂的数据类型, ref 更推荐定义基本类型

ref 和 reactive 本质我们可以简单的理解为ref是对reactive的二次包装, ref定义的数据访问的时候要多一个.value

使用ref定义基本数据类型,ref也可以定义数组和对象。
reactive 不能代理基本类型,例如字符串、数字、boolean 等

toRef与toRefs

前面我们提到Props不能使用使用ES6解构,同样,响应式对象也不能使用ES6解构,但是我们想要解构但有不要失去响应怎么办?这个时候toRef或toRefs就来了。

toRef 可以用来为源响应式对象上的某个 property 新创建一个 ref

toRefs 用于将一个 reactive 对象转化为属性全部为 ref 对象的普通对象。

import { defineComponent, reactive, toRefs, toRef } from "vue";
export default defineComponent({
  setup () {
    const person = reactive({
      name: 'icey',
      age: 18,
      height: 160
    })

    const ageRef = toRef(person, 'age')
    const { age } = toRefs(person)

    ageRef.value++
    console.log(person.age) // 19
    console.log(age.value)  //19

    person.age++
    console.log(ageRef.value) // 20
    console.log(age.value)  //20
  }
})
复制代码

区别

  • toRef 会为源对象不存在的 property生成ref。
  • toRefs 只会为源对象中包含的 property 生成 ref。

当你要将 prop 的 ref 传递给复合函数时,toRef 很有用:
即使源 property 不存在,toRef 也会返回一个可用的 ref。这使得它在使用可选 prop 时特别有用。

computed、watch 与watchEffect

computed 计算属性

  • 接受一个 getter 函数,并为从 getter 返回的值返回一个不变的响应式 ref 对象。
import { defineComponent, computed, ref } from "vue";
export default defineComponent({
  setup () {
    const count = ref(1)
    const plusOne = computed(() => count.value + 1)

    console.log(plusOne.value) // 2
    plusOne.value++
    console.log(plusOne.value) // 2
  }
})
复制代码
  • 使用具有 get 和 set 函数的对象来创建可写的 ref 对象。
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
复制代码
© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享