Vue3 —Composition API 归纳总结

159 阅读4分钟
与Options API 的区别
//Options API 写法
export default {
    components: {},
    data() {},
    computed: {},
    watch: {},
    mouted() {}
}

Options API 官方定义好写法,规定在哪写就在哪写。随着功能增加,代码会更复杂

Composition API 将同一功能逻辑组织在一个函数内部,利于维护,通过setup选项来组织代码

export default {
    setup(props,context) {}
}
setup

是组件内使用Composition API的入口

是一个接收propscontext的函数,其返回的所有内容都暴露给组件的其余部分

注意事项:
  1. 避免使用this
  2. 调用发生在datacoumputedmethods被解析之前
接收参数

props:当传入新的prop时,将被更新;

  1. props是响应式的,当不能使用ES6解构,会消除prop响应性
  2. 解构prop,可以在setup函数里使用**toRefs**函数完成
import { toRef } from 'vue'
setup(props) {
    const title = toRef(props, 'title')
}

context :普通的js对象,暴露了其他可能在setup中有用的值

不是响应式,可以使用ES6解构

访问的property

执行setup时,组件实例尚未被创建。

仅可访问 propsattrsslotsemit

结合模板使用
<!-- MyBook.vue -->
<template>
  <div>{{ collectionName }}: {{ readersNumber }} {{ book.title }}</div>
</template><script>
  import { ref, reactive } from 'vue'
​
  export default {
    props: {
      collectionName: String
    },
    setup(props) {
      const readersNumber = ref(0)
      const book = reactive({ title: 'Vue 3 Guide' })
​
      // 暴露给 template
      return {
        readersNumber,
        book
      }
    }
  }
</script>
使用渲染函数

可以返回一个渲染函数,直接使用在同一作用域中声明的响应状态

import { h, ref, reactive } from 'vue'export default {
  setup() {
    const readersNumber = ref(0)
    const book = reactive({ title: 'Vue 3 Guide' })
    // 请注意这里我们需要显式使用 ref 的 value
    return () => h('div', [readersNumber.value, book.title])
  }
}
ref

可以通过一个新的ref函数使任何响应式变量在任何地方起作用

ref接收参数并将其包裹在一个带有valueproperty的对象中返回,任何可以使用该property访问或更改响应式变量的值

import { ref } from 'vue'const counter = ref(0)
​
console.log(counter) // { value: 0 }
console.log(counter.value) // 0
​
counter.value++
console.log(counter.value) // 1

ref 为值创建了一个响应式引用。

reactive

将对象包装成 响应式对象——通过Proxy代理后的对象,参数必须是对象

ref对象被作为属性,传入响应式对象reactive 时,会自动获取其内部值

const count = ref(0)
const state = reactive({
    count
})
console.log(state.count) // 0
//reactive 属性绑定新的ref对象后,原ref值不变

结合以上知识例子:

<template>
    <div>我的名字:{{name}}</div>
    <div>今天的天气:{{today.weather}}</div>
    <button @click="changWeather">变化天气</button>
</template>
<script>
    import { ref, reactive } from 'vue'
    export default {
        const name = ref('kiya')
        const today = reactive({
            weather: 'sun'
        })
        const changWeather = () =>{
            today.weather = 'rain'
        }
        return {
            name, today
        }
    }
</script>
    // 结果:
    // 我的名字:kiya
    // 今天的天气:sun
    // 点击‘变化天气’
    // 今天的天气:rain
vue 3.2 setup语法糖

<stript>标签里加上setup 关键字就可以。

// 重写以上例子
<template>
    <div>我的名字:{{name}}</div>
    <div>今天的天气:{{today.weather}}</div>
    <button @click="changWeather">变化天气</button>
</template>
<script setup>
    import { ref, reactive } from 'vue'
    const name = ref('kiya')
    const today = reactive({
        weather: 'sun'
    })
    const changWeather = () =>{
        today.weather = 'rain'
    }
    return {
        name, today
    }
</script>
watch 监听

特点:

  • 无法监听未被绑定的属性
  • 可以直接监听 refractive绑定对象

接收3个参数:

  • 想要监听的 响应式引用getter函数
  • 一个回调
  • 可选配置选项
import { ref, watch } from 'vue'
const counter = ref(0)
watch(counter, (newValue,oldValue) => {
    console.log('new counter is' + counter.value)
})
watchEffect

特点:

  • 自动收集数据源作为依赖
  • 无法访问监听状态前后的值
  • 默认会执行一次,属性改变也会执行
const state = reactive({ count:0, name: 'kk'})
setTimeout(() => {
    state.count ++
    state.name = 'oo'
})
watchEffect(() => {
    console.log(state.count)
    console.log(state.name)
})
/* 初次打印: 0 kk
   1秒后打印: 1 oo
 */
computed
  1. 接收一个getter函数,并根据 getter 的返回值返回一个不可变的响应式ref对象。
  2. 接收具有getset函数对象,用来创建可以写的ref对象
import { computed } from 'vue'
//1 getter
const count = ref(1)
const plusOne = computed(() => count.value + 1)
console.log(plusOne.value) // 2//2 get set
const plusOne = computed({
    get: () => count.value + 1,
    set: val => {
        count.value = val -1
    }
})
生命周期函数

只能同步的使用在setup函数里面。

vue3 相比 vue2 减少了beforeCreate 和 Created,因为setup是为了这两个生命周期钩子运行的。

生命周期对比
Options APIsetup
beforeCreateNot needed*
createdNot needed*
beforeMountonBeforeMount
mountedonMounted
beforeUpdateonBeforeUpdate
updatedonUpdated
beforeUnmountonBeforeUnmount
unmountedonUnmounted
errorCapturedonErrorCaptured
renderTrackedonRenderTracked
renderTriggeredonRenderTriggered
activatedonActivated
deactivatedonDeactivated

这些函数接收一个回调函数,钩子被调用时会被执行。

子父级传值——define

注意:

define类api必须在setup中外层使用,无法放入方法中

和TS兼容不太好

defineProps

定义props相关信息

// 基础写法
defineProps({
    tags:Array
})
// TS 类型声明
const props = defineProps<{
    tags:Array
}>()

两种写法不能一起使用。

defineEmits

定义emits相关信息

//基础用法
const emit = defineEmits(['change', 'delete'])
emits('change')
​
// TS声明类型
const emit = defineEmits<{
    (e:'change', id:number):void
    (e:'update', value:string):void
}>()
emits('change',1)
defineExpose

抛出方法

const getData = () => {
    emit('getData','给父组件的值') 
    //触发父组件的方法
}
const setData  = (val) => {
    fatherData.value = val
    //父组件调用
}
defineExpose({
    getData,
    setData
})

父组件调用子组件,需要子组件先定义好方法,通过defineExpose暴露出去。