Vue3中的composition API的知识总结(一)

​ 最近这个几个月都在跟着coderwhy老师,系统性的学习Vue3的新知识,和新特性。首先,先感谢coderwhy老师讲的非常的好,真的很赞,我这种脑子转的很慢的人,都可以跟上他的节奏,非常感谢老师。

​ 老师教的好,但是并不代表我就以前完全的吸收了,代码这个东西,不长期练习,总是会忘的,所以自己打算做个总结,忘的时候,在瞄一眼吧。好了,开始正题吧!

认识 Composition API

Vue3最大的特色 就是 Composition API咯。

Composition API : 一组低侵入式的、函数式的 API,它使我们能够更灵活地「组合」组件的逻辑。

如果写过react的话,就感觉很熟悉了。

Vue3中的 Composition API 和 Vue2中的Options API的对比

在这里插入图片描述

​ 主要的区别就是,vue2中Options API的对一个功能的逻辑代码比较分散,当项目大了,就非常的难以维护。 而在Vue3中的Composition API 就很好的解决了,此类问题,阅读性更加的强,如果项目大了,还可单独提出来,封装成一个函数,放在其他的文件。

使用Composition API

​ 来了来了, GO GO GO!

​ 这里Vue3使用ts重构的,所以我也用ts代码来展示。

setup()

​ composition API提供的函数都是在setup中使用的,所以我们需要了解setup这个函数。

​ setup函数,就像Options API中使用, 增加一个属性

<script lang="ts">
    //defineComponent 函数是用来支持ts语法的
    import { defineComponent } from 'vue'

    export default defineComponent({
          setup() {
			
          }
    })
</script>

setup的执行时期

export default defineComponent({
      beforeCreate() {
        console.log('beforeCreate', this);
      },
      created() {
        console.log('created', this)
      },
      setup() {
        console.log('setup', this);
      }
})

在Vue2中,我们知道,beforeCreate是最先执行的生命周期函数。 那么,上面的代码呢?

结果

在这里插入图片描述

上面的截图,我们可以发现,setup中是最先执行的,并且其中的this为undefined,是因为setup的调用发生在data property, computed property或methods解析之前,所以在setup中拿去不到

所以,千万注意,不能在setup中使用this

setup的参数

setup接受两个参数

  • 第一个参数:props 父组件传递过来的

  • 第二个参数:是一个对象,包含三个可用的属性

export default defineComponent({
  props: {
    message: {
      type: String,
      require: true,
      default: '默认值'
    }
  },
  setup(props) {
    console.log(props);
  }
})

需要注意的时,我们接受父组件传递出来的props,还是跟Options API中一样的定义Props,又因为在setup中拿不到this,所以第一个参数提供props,为了让我们拿到props

第二个参数: 是一个对象,包含:

  • attrs:所有的非props的attribute(id, class等等)在组件上写的属性,但是不是为了传递下来
  • emit: 提供子组件发出事件给父组件(因为不能通过this.$emit这种方式来触发)
  • expose: 这个暂时不知道,请大佬告知
  • slots: 父组件传递过来的插槽使用(只会在h函数中使用到)

代码示例:

// attrs

//父组件
<Son message="james" class="my-son"/>
    
//子组件
export default defineComponent({
  props: {
    message: {
      type: String,
      require: true,
      default: '默认值'
    }
  },
  setup(props, {attrs}) {
      //class是非attribute
    console.log(attrs)  // Proxy {class: "my-son", __vInternal: 1}
  }
})
#slots 怎么使用,目前还没接触到,如果有遇到,在补充(尴尬,其实是自己不会,研究了一下,不会用)
// emit

//父组件
<template>
  <div id="nav">
      //接受子组件派发的事件
    <Son @getSonFn="useSonFn" />
  </div>
</template>

<script lang="ts">
import { defineComponent } from 'vue'
import Son from '@/views/Son.vue'

export default defineComponent({
  components: {
    Son
  },
  setup() {
      const useSonFn = () => {
        console.log(1111);
        
      }
      return {
        useSonFn
      }
  }
})
</script>

//子组件 Son.vue
<template>
  <div id="nav">
    <button @click="btn">点击,派发事件</button>
  </div>
</template>

<script lang="ts">
import { defineComponent } from 'vue'

export default defineComponent({
  emits: ['getSonFn'],
  setup(props, {emit}) {
    const btn = () => {    //点击按钮,派发getSonFn事件,给父组件
        emit('getSonFn')    //当然后面也可以传递参数
    }
    return {
        btn
    }
  }
})
</script>

setup的返回值

setup函数跟Vue2的data函数一样,必须返回一个对象。

对象的属性值,用于渲染template模板上。

reactive()

返回对象的响应式副本。(传入一个对象返回一个基于原对象的响应式代理,即返回一个proxy)

类型声明:

type UnwrapNestedRefs<T> = T extends Ref ? T : UnwrapRef<T>
    
function reactive<T extends object>(target: T): UnwrapNestedRefs<T>

基本使用:

import { defineComponent, reactive } from 'vue'

interface InfoType {
  name: string;
  age: number;
}

export default defineComponent({
  setup() {
      //泛型 InfoType
      const info = reactive<InfoType>({name: 'james', age: 12})
      
      return {}
  }
})

解释:

  • 这是因为我们当使用reactive函数处理数据之后,数据再次被使用时就会进行依赖收集
  • 当数据发生变化时,所有收集的依赖都是进行对应的响应式操作(UI更新)
  • 实际上,options API 中的data选项,也是交给了reactive来进行处理的

ref()

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

类型声明:

interface Ref<T> {
  value: T
}

function ref<T>(value: T): Ref<T>

基本使用:

import { ref } from 'vue'

const count = ref(0)     //基本数据类型   会进行类型推断(这里就为number)
//等价于
const count = ref<number>(0)
console.log(count.value) // 0

count.value++
console.log(count.value) // 1

<template>
    <div>{{count}}</div>      //解包
</template>

解释:

  • ​ ref 对象 在template中使用的使用,会进行解包操作(浅层解包)
const count = ref<number>(123)
const countInfo = {   //使用一个普通对象包裹
    countInfo
}
return {    //返回普通对象
    countInfo    
}

//这里,它不会接解包
<div>{{countInfo.countInfo}}</div>          //错误的写法
<div>{{countInfo.countInfo.value}}</div>    //正确的写法
const name = ref('james')
//把name放在一个reactive函数包裹的对象中
const info = reactive({
    name
})
//这里,它会进行解包
<div>{{info.name}}</div>    //正确的写法

readonly()

获取一个对象 (响应式或纯对象) 或 ref并返回原始代理的只读代理。只读代理是深层的:访问的任何嵌套 property 也是只读的。

简单来说, readonly函数接受reactive()ref()创建的属性,然后返回的对象只能读, 不能写。

基本使用:

import { readonly } from 'vue'
const name1 = reactive({
    name: 'james'
})
const readonlyName = readonly(name1)

//readonlyName 就不能被修改了,会被报警告

const name1 = ref('kobe')
const readonlyName = readonly(name1)

使用场景:

封装一个组件,内部的值,readonly包裹传递过去,允许内部修改reactive和ref属性,但是不允许外部修改。

isProxy()

检查对象是否由reactivereadonly创建的proxy。

如果是,返回true, 否则,返回false

基本使用:

const info = reactive<InfoType>({name: 'james', age: 12})
const readonlyInfo = readonly(info)
const is = isProxy(readonlyInfo)   //true

isReactive()

检查对象是否是 reactive创建的响应式 proxy。

如果 proxy 是 readonly 创建的,但还包装了由 reactive 创建的另一个 proxy,它也会返回 true

基本使用:

import { reactive, isReactive, readonly } from 'vue'
export default {
  setup() {
    const state = reactive({
      name: 'John'
    })
    // 从普通对象创建的只读代理
    const plain = readonly({
      name: 'Mary'
    })
    console.log(isReactive(plain)) // -> false

    // 从响应式代理创建的只读代理
    const stateCopy = readonly(state)
    console.log(isReactive(stateCopy)) // -> true
  }
}

isReadonly()

检查对象是否是由readonly创建的只读代理。

toRaw()

返回reactive或readonly代理的原始对象(不建议保留对原始对象的持久引用,谨慎使用)

shallowReactive()

创建一个响应式代理,它跟踪其自身property的响应式,但是不执行嵌套对象的深层响应式转化(深层还是原生对象)

基本使用:

const obj = shallowReactive({name: 'james', obj: {age: '12'}})

//这里就只监听第一层对象,第二层对象就监听不到了,还是原生的对象
//reactive就不一样了,可以随时监听多层

shallowReadonly()

创建一个代理,使其自身的 property 为只读,但不执行嵌套对象的深度只读转换 (暴露原始值)。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值