初见Vue3 Composition API的疑问

390 阅读2分钟

Vue3 推出了Composition API的新特性,相信大家都已经学习过了,官方文档上的教程写的也很详细。

v3.cn.vuejs.org/guide/compo…

但是有些官方文档中没有提到,但在使用过程中会遇到的问题,让我来探究一下。

两种生命周期钩子

在Composition API中可以声明生命周期钩子函数,对于以前的选项式生命周期钩子,除了beforeCreatecreated没有外,其它都有相对应的。

v3.cn.vuejs.org/guide/compo…

那么两种生命周期可以共存吗?如果可以的话,执行顺序是怎么样的呢?

示例:

import { onBeforeMount, onMounted } from 'vue'

export default {
  setup() {
    console.log('setup')
    onBeforeMount(() => {
      console.log('onBeforeMount')
    })
    onMounted(() => {
      console.log('onMounted')
    })
  },
  beforeCreate() {
    console.log('beforeCreate')
  },
  created() {
    console.log('created')
  },
  beforeMount() {
    console.log('beforeMount')
  },
  mounted() {
    console.log('mounted')
  }
}

输出的结果为:

setup
beforeCreate
created
onBeforeMount
beforeMount
onMounted
mounted

所以,在setuponBeforeMountbeforeMounted分别先于beforeMountmounted触发。对于onBeforeUpdateonUpdatedonBeforeUnmountonUnmounted,情况是一样的。

ref和DOM

ref可以创建一个响应式的变量,比如:

<template>
    <div @click="count++">{{count}}</div>
</template>

<script>
import { ref } from 'vue'

export default {
    setup(){
        const count = ref(0)
    
        return {
            count
        }
    }
}
</script>

ref也可以用来建立对DOM元素的引用,比如:

<template>
    <div ref="content"></div>
</template>

<script>
import { ref, onMounted } from 'vue'

export default {
    setup(){
        const content = ref(null)
        
        onMounted(()=>{
            console.log(content.value) // <div></div>
        })
    
        return {
            content
        }
    }
}
</script>

setup函数返回的变量中有和模板中ref值相同的变量时,相对应的DOM引用会赋值到变量上。

初看这一点会让人有点迷惑,因为一般的用法是使用$refs来获取DOM元素,但是ref还有另一种函数声明方法:

<template>
    <div ref="el => content = el"></div>
</template>

在Composition API中直接传递字符串应该是这种方式的语法糖。

引入组件

一般情况下,我们引入本地组件是这样的:

<template>
    <c />
</template>

<script>
import C from 'c'

export default {
    components:{
        c: C
    }
}
</script>

在Vue3.2的setup语法糖中,我们引入component的语句自动被转换为组件注册:

<template>
    <c />
</template>

<script setup>
import C from 'c'
</script>

默认情况下,组件使用连字符命名方式。

那如果组件不是直接导出而是被包含在一个对象中呢?

比如:

<template>
    <c />
</template>

<script>
import W from 'w'

export default {
    components:{
        c: W.C
    }
}
</script>

此时只需要需要创建一个变量

<template>
    <c />
</template>

<script setup>
import W from 'w'

const c = W.C
</script>

引入指令

引入的组件会被自动注册,那指令改如何注册呢?

与组件类似,引入的指令也会被自动注册,但是在名称上需要些许修改。

因为我们在使用指令时通常是v-x的格式,所有我们在引入指令时,需要把名称改为vX的格式:

<template>
    <div v-x></div>
</template>

<script setup>
import {x as vX} from 'X'
</script>

异步setup

setup方法可以是异步的吗?即:

async setup(){}

从实验结果来看,在一般的组件中,setup方法不能是异步的。如果是异步函数,组件的初始化过程会中断。

但是在与suspense配合的异步组件中可以使用异步的setup方法。