setup

  • 不同于 ReactivityApi,CompositionApi 提供的函数很多是与组件深度绑定的,不能脱离组件而存在
  • 新的 option, 所有的组合 API 函数都在此使用, 只在初始化时执行一次
  • 函数如果返回对象, 对象中的属性或方法, 模板中可以直接使用;
<template>
  <div>hello</div>
  <h1>{{ number }}</h1>
</template>

<script lang="ts">
// defineComponent函数,目的是定义一个组件,内部可以传入一个配置对象
import { defineComponent } from "vue";

// defineComponent 最重要的是:在 TS 下,给予了组件正确的参数类型推断 
export default defineComponent({
  // 当前组件的名字是 App
  name: "App",
  // 测试代码 setup 是组合 API 中第一个要使用的函数
  setup() {
    const number = 10;
    return {
      number,
    };
  },
});
</script>

setup 的参数

setup(props, context) / setup(props, {attrs, slots, emit})

  1. props: 和 vue2 中的 props 作用一样;

  2. attrs: 包含没有在 props 配置中声明的属性的对象, 相当于 this.$attrs;

  3. slots: 包含所有传入的插槽内容的对象, 相当于 this.$slots;

  4. emit: 用来分发自定义事件的函数, 相当于 this.$emit;

setup 执行的时机

  1. 在解析完 props、beforeCreate 之前执行(一次), 此时组件对象还没有创建(此时没有this);

  2. this 是 undefined, 不能通过 this 来访问 data/computed/methods/props,其实所有的 composition API 相关回调函数中也都不可以;

setup 的返回值

  1. 一般都返回一个对象: 为模板提供数据, 也就是模板中可以直接使用此对象中的所有属性/方法;

    • 返回对象中的属性会与 data 函数返回对象的属性合并成为组件对象的属性;
    • 返回对象中的方法会与 methods 中的方法合并成功组件对象的方法;
    • 如果有重名, setup 优先;
  2. 注意:

    • 一般不要混合使用: methods 中可以访问 setup 提供的属性和方法, 但在 setup 方法中不能访问 data 和 methods;
    • setup 不能是一个 async 函数: 因为返回值不再是 return 的对象, 而是 promise, 模板获取不到 return 对象中的属性数据;

生命周期

生命周期图解

生命周期函数

vue2 option api vue3 option api vue 3 composition api
beforeCreate beforeCreate 不再需要,代码可直接置于 setup 中
created created 不再需要,代码可直接置于 setup 中
beforeMount beforeMount onBeforeMount
mounted mounted onMounted
beforeUpdate beforeUpdate onBeforeUpdate
updated updated onUpdated
beforeDestroy beforeUnmount onBeforeUnmount
destroyed unmounted onUnmounted
errorCaptured errorCaptured onErrorCaptured
- renderTracked onRenderTracked
- renderTriggered onRenderTriggered

新增钩子函数说明

DebuggerEvent:

  • target: 跟踪或触发渲染的对象
  • key: 跟踪或触发渲染的属性
  • type: 跟踪或触发渲染的方式
钩子函数 参数 执行时机
renderTracked DebuggerEvent 渲染vdom收集到的每一次依赖时
renderTriggered DebuggerEvent 某个依赖变化导致组件重新渲染时

父子组件声明周期顺序

示例代码

  1. app.vue

    <template>
      <h2>App父级组件</h2>
      <button @click="isShow = !isShow">切换显示</button>
      <hr />
      <!-- 子级组件 -->
      <Child v-if="isShow" />
    </template>
    <script lang="ts">
    // 引入子级组件Child
    import Child from './components/Child.vue';
    import { defineComponent, ref } from 'vue';
    export default defineComponent({
      name: 'App',
      // 注册组件
      components: {
        Child,
      },
      setup() {
        const isShow = ref(true);
        return {
          isShow,
        };
      },
    });
    </script>
    
  2. child.vue

    <template>
      <h2>Child子级组件</h2>
      <h4>msg:{{ msg }}</h4>
      <button @click="update">更新数据</button>
    </template>
    <script lang="ts">
    import {
      defineComponent,
      ref,
      onBeforeMount,
      onMounted,
      onBeforeUpdate,
      onUpdated,
      onBeforeUnmount,
      onUnmounted } from 'vue';
    export default defineComponent({
      name: 'Child',
      // vue2.x 中的生命周期钩子
      beforeCreate() {
        console.log('2.x中的beforeCreate...');
      },
      created() {
        console.log('2.x中的created...');
      },
      beforeMount() {
        console.log('2.x中的beforeMount...');
      },
      mounted() {
        console.log('2.x中的mounted...');
      },
      beforeUpdate() {
        console.log('2.x中的beforeUpdate...');
      },
      updated() {
        console.log('2.x中的updated...');
      },
      // vue2.x 中的 beforeDestroy 和 destroyed 这两个生命周期在 vue3 中改名了,所以,不能再使用了
      beforeUnmount() {
        console.log('2.x中的beforeUnmount...');
      },
      unmounted() {
        console.log('2.x中的unmounted...');
      },
      setup() {
        console.log('3.0中的setup');
        // 响应式的数据
        const msg = ref('abc');
        // 按钮点击事件的回调
        const update = () => {
          msg.value += '===';
        };
        onBeforeMount(() => {
          console.log('3.0中的onBeforeMount');
        });
        onMounted(() => {
          console.log('3.0中的onMounted');
        });
        onBeforeUpdate(() => {
          console.log('3.0中的onBeforeUpdate');
        });
        onUpdated(() => {
          console.log('3.0中的onUpdated');
        });
        onBeforeUnmount(() => {
          console.log('3.0中的onBeforeUnmount');
        });
        onUnmounted(() => {
          console.log('3.0中的onUnmounted');
        });
        return {
          msg,
          update,
        };
      },
    });
    </script>
    

效果展示

  1. 初始化

  2. 更新

  3. 销毁

面试题

composition api相比于option api有哪些优势?

从两个方面回答:

  1. 为了更好的逻辑复用和代码组织
  2. 更好的类型推导
  1. 有了 composition api 配合 reactivity api,可以在组件内部进行更加细粒度的控制,使得组件中不同的功能高度聚合,提升了代码的可维护性;对于不同组件的相同功能,也能够更好的复用;

  2. 相比于 option apicomposition api 中没有了指向奇怪的 this ,所有的 api 变得更加函数式,这有利于和类型推断系统比如 TS 深度配合;

打赏作者
您的打赏是我前进的动力
微信
支付宝
评论

中午好👏🏻,我是 ✍🏻   疯狂 codding 中...

粽子

这有关于前端开发的技术文档和你分享。

相信你可以在这里找到对你有用的知识和教程。

了解更多

目录

  1. 1. setup
    1. 1.1. setup 的参数
    2. 1.2. setup 执行的时机
    3. 1.3. setup 的返回值
  2. 2. 生命周期
    1. 2.1. 生命周期图解
    2. 2.2. 生命周期函数
    3. 2.3. 新增钩子函数说明
    4. 2.4. 父子组件声明周期顺序
      1. 2.4.1. 示例代码
      2. 2.4.2. 效果展示
  3. 3. 面试题
    1. 3.1. composition api相比于option api有哪些优势?