vue3 组合式API composition 简单使用

composition api 组合式API

官网文档

通过创建 Vue 组件,可以将界面中重复的部分连同其功能一起提取为可重用的代码段。

使用 (datacomputedmethodswatch) 组件选项来组织逻辑通常都很有效。然而,当组件开始变得更大时,逻辑关注点的列表也会增长。尤其对于那些一开始没有编写这些组件的人来说,这会导致组件难以阅读和理解。

这种碎片化使得理解和维护复杂组件变得困难。选项的分离掩盖了潜在的逻辑问题。此外,在处理单个逻辑关注点时,必须不断地“跳转”相关代码的选项块。

如果能够将同一个逻辑关注点相关代码收集在一起会更好。而这正是组合式 API 能够做到的。

composition api 为vue应用提供更好的逻辑复用和代码组织。

setup 组件选项

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

注意:在 setup 中应该避免使用 this,因为它不会找到组件实例。setup 的调用发生在 data property、computed property 或 methods 被解析之前,所以它们无法在 setup 中被获取。

setup 选项是一个接收 propscontext 的函数。此外,将 setup 返回的所有内容都暴露给组件的其余部分 (计算属性、方法、生命周期钩子等等) 以及组件的模板。

ref 的响应式变量

在 Vue 3.0 中,可以通过一个新的 ref 函数使任何响应式变量在任何地方起作用,如下所示:

import { ref } from 'vue'

const counter = ref(0)

ref 接收参数并将其包裹在一个带有 value property 的对象中返回,然后可以使用该 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

将值封装在一个对象中,看似没有必要,但为了保持 JavaScript 中不同数据类型的行为统一,这是必须的。这是因为在 JavaScript 中,NumberString 等基本类型是通过值而非引用传递的。

在任何值周围都有一个封装对象,这样就可以在整个应用中安全地传递它,而不必担心在某个地方失去它的响应性。

提示:换句话说,ref 为值创建了一个响应式引用。在整个组合式 API 中会经常使用引用的概念。

setup 内注册生命周期钩子

为了使组合式 API 的功能和选项式 API 一样完整,还需要一种在 setup 中注册生命周期钩子的方法。这要归功于 Vue 导出的几个新函数。组合式 API 上的生命周期钩子与选项式 API 的名称相同,但前缀为 on:即 mounted 看起来会像 onMounted

这些函数接受一个回调,当钩子被组件调用时,该回调将被执行。

watch 响应式更改

就像在组件中使用 watch 选项并在 data property 上设置侦听器一样,也可以使用从 Vue 导入的 watch 函数执行相同的操作。

它接受 3 个参数:

  • 一个想要侦听的响应式引用或 getter 函数
  • 一个回调
  • 可选的配置选项

它是如何工作的

import { ref, watch } from 'vue'

const counter = ref(0)
watch(counter, (newValue, oldValue) => {
  console.log('The new counter value is: ' + counter.value)
})

每当 counter 被修改时,例如 counter.value=5,侦听将触发并执行回调 (第二个参数),在本例中,它将把 'The new counter value is:5' 记录到控制台中。

以下是等效的选项式 API:

export default {
  data() {
    return {
      counter: 0
    }
  },
  watch: {
    counter(newValue, oldValue) {
      console.log('The new counter value is: ' + this.counter)
    }
  }
}

独立的 computed 属性

refwatch 类似,也可以使用从 Vue 导入的 computed 函数在 Vue 组件外部创建计算属性。

import { ref, computed } from 'vue'

const counter = ref(0)
const twiceTheCounter = computed(() => counter.value * 2)

counter.value++
console.log(counter.value) // 1
console.log(twiceTheCounter.value) // 2

这里给 computed 函数传递了第一个参数,它是一个类似 getter 的回调函数,输出的是一个只读响应式引用

为了访问新创建的计算变量的 value,需要像 ref 一样使用 .value property。

reactive

官方文档

返回对象的响应式副本

const obj = reactive({ count: 0 })

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

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

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

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

// 它也会更新 `count` ref
obj.count++
console.log(obj.count) // 3
console.log(count.value) // 3

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

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

obj.count = count

console.log(obj.count) // 1
console.log(obj.count === count.value) // true

ref

官方文档

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

示例:

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

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

如果将对象分配为 ref 值,则它将被 reactive 函数处理为深层的响应式对象。

toRefs

官方文档

将响应式对象转换为普通对象,其中结果对象的每个 property 都是指向原始对象相应 property 的 ref

当从组合式函数返回响应式对象时,toRefs 可以在不丢失响应性的情况下对返回的对象进行解构/展开。

export default{
    setup(){
        const state = reactive({
            foo: 1,
            bar: 2
        })
        return {...toRefs(state)}
    }
}

组合式API应用示例

<template>
  <div>
    <p>counter: {{counter}}</p>
    <p>doubleCounter: {{doubleCounter}}</p>
    <p ref="desc"></p>
  </div>
</template>

<script>
import { reactive,computed,watch,ref,toRefs,onMounted,onUnmounted } from "vue";

export default {
    setup() {
        const data = reactive({
            counter: 1,
            doubleCounter: computed(() => data.counter * 2),
        });

        let timer

        onMounted(() => {
            timer = setInterval(() => {
                data.counter++
            }, 1000);
        })

        onUnmounted(() => {
            clearInterval(timer)
        })

        const desc = ref(null)

        watch(()=>data.counter, (val,oldVal)=>{
            console.log(`counter change from ${oldVal} to ${val}`);
            desc.value.textContent = `counter change from ${oldVal} to ${val}`
        })

        return {...toRefs(data), desc};
    },
};
</script>

你可能感兴趣的:(前端,vue,vue3,composition,组合式,API)