灵活运用Vue 3中的setup函数—深入解析Composition API

在这里插入图片描述

新建项目,项目主入口为App.vue(主组件),新建child.vue(子组件)。

image-20230319152907890

1.1 setup 执行 时机问题

1.在主组件里引入子组件和ref:

import {ref} from 'vue'
import child from './components/child.vue'

2.template层:写一些基本提示性语句

<template>
   <h1>父组件</h1>
   <h3>{{ msg }}</h3>
   <button @click="msg +='你好'">更新数据</button>
   <hr>
   <child :msg="msg"/>
</template>

3.注册放行子组件:

neme: 'App',
  //注册
  components: {
    child
  },

4.写setup方法:

setup() {
    const msg = ref("11")
    return {
        msg,
    }
},

5.子组件如下:使用props获取到父组件的值,查看beforeCreate和setup的执行顺序。

export default {
    name:'child',
    props:['msg'],
    beforeCreate(){
        console.log("beforeCreate执行");
    },
    setup(){
        console.log("setup执行了");
        return
    }
}

6.子组件template

<template>
   <h2>子组件</h2>
   <h3>msg:{{ msg }}</h3>
</template>

1.1.1 总结

1.setup 中一般都是返回一个对象,对象中的属性和方法都可以在 html 模版中直接使用

2.setup 是在 before Create 生命周期回调之前就执行了, 而且就执行一次

3.由此可以推断出:setup 在执行的时候, 当前的组件还没有创建出来, 也就意味着:组件实例对象 this 根本就不能用

this 是 undefined, 说明, 就不能通过 this 再去调用 data/computed/methods 中的相关内容了

1.2 setup细节

  • setup执行的时机
    • 在beforeCreate之前执行(一次), 此时组件对象还没有创建
    • this是undefined, 不能通过this来访问data/computed/methods / props
    • 其实所有的composition API相关回调函数中也都不可以
  • setup的返回值
    • 一般都返回一个对象: 为模板提供数据, 也就是模板中可以直接使用此对象中的所有属性/方法
    • 返回对象中的属性会与data函数返回对象的属性合并成为组件对象的属性
    • 返回对象中的方法会与methods中的方法合并成功组件对象的方法
    • 如果有重名, setup优先
    • 注意:
    • 一般不要混合使用: methods中可以访问setup提供的属性和方法, 但在setup方法中不能访问data和methods
    • setup不能是一个async函数: 因为返回值不再是return的对象, 而是promise, 模板看不到return对象中的属性数据
  • setup的参数
    • setup(props, context) / setup(props, {attrs, slots, emit})
    • props: 包含props配置声明且传入了的所有属性的对象
    • attrs: 包含没有在props配置中声明的属性的对象, 相当于 this.$attrs
    • slots: 包含所有传入的插槽内容的对象, 相当于 this.$slots
    • emit: 用来分发自定义事件的函数, 相当于 this.$emit
<template>
  <h2>App</h2>
  <p>msg: {{msg}}</p>
  <button @click="fn('--')">更新</button>

  <child :msg="msg" msg2="cba" @fn="fn"/>
</template>

<script lang="ts">
import {
  reactive,
  ref,
} from 'vue'
import child from './child.vue'

export default {

  components: {
    child
  },

  setup () {
    const msg = ref('abc')

    function fn (content: string) {
      msg.value += content
    }
    return {
      msg,
      fn
    }
  }
}
</script>
<template>
  <div>
    <h3>{{n}}</h3>
    <h3>{{m}}</h3>

    <h3>msg: {{msg}}</h3>
    <h3>msg2: {{$attrs.msg2}}</h3>

    <slot name="xxx"></slot>

    <button @click="update">更新</button>
  </div>
</template>

<script lang="ts">

import {
  ref,
  defineComponent
} from 'vue'

export default defineComponent({
  name: 'child',

  props: ['msg'],

  emits: ['fn'], // 可选的, 声明了更利于程序员阅读, 且可以对分发的事件数据进行校验

  data () {
    console.log('data', this)
    return {
      // n: 1
    }
  },

  beforeCreate () {
    console.log('beforeCreate', this)
  },

  methods: {
    // update () {
    //   this.n++
    //   this.m++
    // }
  },

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

    console.log('setup', this)
    console.log(props.msg, attrs.msg2, slots, emit)

    const m = ref(2)
    const n = ref(3)

    function update () {
      // console.log('--', this)
      // this.n += 2 
      // this.m += 2

      m.value += 2
      n.value += 2

      // 分发自定义事件
      emit('fn', '++')
    }

    return {
      m,
      n,
      update,
    }
  },
})
</script>

这是一个关于Vue 3的组件开发和setup函数使用的示例。我看到你提供了一个父组件 App.vue 和一个子组件 child.vue 的代码,以及关于setup函数的一些细节和总结。

首先,让我简要概括一下你的代码:

  • 在主组件 App.vue 中,你引入了子组件 child.vueref 函数。在模板中,你展示了一些基本的提示性语句,并包含一个更新数据的按钮和子组件 child
  • 你在 setup 函数中初始化了一个 msg 的响应式引用,并返回了这个引用,使其在模板中可用。
  • 子组件 child.vue 中,你使用 props 获取了父组件传递的值,并在 beforeCreatesetup 生命周期钩子中输出了一些信息。在模板中,你展示了父组件传递的消息。

接下来,让我帮你继续写下去:

setup函数的更多用法

setup函数中,可以执行各种初始化逻辑,包括对props的处理、引入其他模块、设置定时器等。

// 在 App.vue 的 setup 函数中
import { onMounted, onUnmounted } from 'vue';

setup() {
    const msg = ref("1");

    // 添加一个计时器,每秒更新一次数据
    const timer = setInterval(() => {
        msg.value += '!';
    }, 1000);

    // 在组件挂载时启动计时器
    onMounted(() => {
        console.log('组件挂载了!');
    });

    // 在组件卸载时清除计时器
    onUnmounted(() => {
        clearInterval(timer);
        console.log('组件卸载了!');
    });

    return {
        msg,
    };
},

引入了onMountedonUnmounted函数,它们分别在组件挂载和卸载时执行。在挂载时,启动了一个计时器,每秒更新一次数据;在卸载时清除了计时器。

这样, App.vue 组件现在会在挂载时启动一个定时器,在卸载时清除定时器。

当然,继续讨论 Vue 3 中 setup 函数的更多用法和细节。

1.3 setup 函数的参数

在之前的例子中,我们在 setup 函数中只使用了 setup(),但实际上,setup 函数可以接受两个参数:propscontext(或者可以使用解构语法分别获取 attrsslotsemit)。这两个参数提供了更多的灵活性和访问权限。

App.vue 中,我们可以修改 setup 函数,接受 propscontext 参数:

setup(props, context) {
    const msg = ref("111");

    // 访问 props
    console.log(props.msg);

    // 访问 context,包含 attrs、slots 和 emit
    console.log(context.attrs.msg2);
    console.log(context.slots);
    console.log(context.emit);

    return {
        msg,
    };
},

这样,我们就可以更灵活地处理传递给组件的属性以及与组件的上下文进行交互。

1.4 使用 Composition API

setup 函数是 Composition API 的一部分,它使得组件逻辑可以更灵活地组织和重用。在 setup 函数中,我们可以使用诸如 reactiverefwatch 等 Composition API 提供的功能。

setup() {
    const msg = ref("11");
    const count = ref(0);

    // 使用 watch 监听数据变化
    watch(() => msg.value, (newVal, oldVal) => {
        console.log(`消息从 ${oldVal} 更新为 ${newVal}`);
    });

    // 使用 reactive 创建响应式对象
    const state = reactive({
        name: "Vue 3",
        version: "3.0.0",
    });

    return {
        msg,
        count,
        state,
    };
},

这个例子中,我们使用了 watch 监听 msg 的变化,并使用 reactive 创建了一个包含 nameversion 的响应式对象 state

1.5 组合式函数的提取和重用

由于 setup 函数的灵活性,我们可以将一些逻辑提取为组合式函数,以便在多个组件中重用。例如,我们可以创建一个处理数据的函数:

// utilities.js
import { ref } from 'vue';

export function useData(initialValue) {
    const data = ref(initialValue);

    function updateData() {
        data.value += '!';
    }

    return {
        data,
        updateData,
    };
}

然后在 setup 函数中使用:

// App.vue
import { useData } from './utilities.js';

setup() {
    const { data: msg, updateData } = useData("111");

    return {
        msg,
        updateData,
    };
},

这样,我们可以更好地组织和重用代码。

1.6 注意事项

在使用 setup 函数时,需要注意一些事项:

  • 不要混合使用 setupdatamethods 等选项。在 setup 中可以访问 props,但在 datamethods 中无法访问 setup 中的属性和方法。
  • setup 函数不能是异步的,因为返回值将不再是一个对象,而是一个 Promise

1.7 插槽(Slots)和自定义事件

在 Vue 3 中,使用 setup 函数也能够更方便地处理插槽和自定义事件。在 child.vue 组件中,我们已经看到了如何使用插槽和自定义事件:

// child.vue
setup(props, { attrs, emit, slots }) {
    const m = ref(2);
    const n = ref(3);

    function update() {
        m.value += 2;
        n.value += 2;

        // 分发自定义事件
        emit('fn', '++');
    }

    return {
        m,
        n,
        update,
    };
},

在这个例子中,我们使用 emit 函数来分发自定义事件,父组件 App.vue 可以监听这个事件并执行相应的逻辑。

1.8 生命周期钩子

setup 函数中,Vue 3 提供了两个新的生命周期钩子函数:onBeforeMountonBeforeUnmount。这两个钩子分别在组件挂载前和卸载前执行:

// App.vue
setup() {
    const msg = ref("11");

    onBeforeMount(() => {
        console.log('组件即将挂载!');
    });

    onBeforeUnmount(() => {
        console.log('组件即将卸载!');
    });

    return {
        msg,
    };
},

这样,我们可以在组件生命周期的不同阶段执行特定的逻辑。

1.9 组件引入和注册

App.vue 中,我们使用 import 语句引入了 child.vue 组件,并使用 components 选项注册了这个组件:

// App.vue
import child from './components/child.vue';

export default {
    components: {
        child,
    },
    // ...
};

这样,我们就可以在模板中直接使用这个组件。

1.10 总结

通过这个例子,我们更深入地了解了 Vue 3 中 setup 函数的使用方式和一些注意事项。Composition API 提供了更灵活和可复用的代码组织方式,让我们能够更好地处理组件的逻辑。

setup 函数中,我们可以访问 propscontext,使用 Composition API 的功能,处理插槽和自定义事件,以及执行一些生命周期钩子。这使得我们能够更好地组织和重用组件的代码。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/177241.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

12英寸双轴半自动划片机:颠覆传统划切工艺的五大优势

随着科技的飞速发展&#xff0c;半导体行业对精密划切设备的需求日益增长。在这篇文章中&#xff0c;我们将深入探讨12英寸双轴半自动划片机的优势&#xff0c;这种划片机在半导体制造过程中扮演着至关重要的角色。以下是这种划片机的五大优势。 一、高精度划切 12英寸双轴半自…

二十二、数组(4)

本章概要 随机生成泛型和基本数组 随机生成 我们可以按照 Count.java 的结构创建一个生成随机值的工具&#xff1a; Rand.java import java.util.*; import java.util.function.*;import static com.example.test.ConvertTo.primitive;public interface Rand {int MOD 10_0…

89. 格雷编码

89. 格雷编码 Java代码&#xff1a;2DFS class Solution {List<Integer> res new ArrayList<>();public List<Integer> grayCode(int n) {dfs(n, new StringBuffer(), new int[]{0, 1});return res;}public void dfs(int n, StringBuffer sb, int[] nums){i…

如何用【测试思维】做“支付功能”测试?

前言 跳槽高峰期&#xff0c;作为测试&#xff0c;不管是面试还是笔试&#xff0c;必然要被考验到的就是”测试思维“。在面试中就是体现在如下面试题中&#xff1a; “说说你项目中的 xx 模块你是如何测试的&#xff1f;” “给你一个购物车&#xff0c;你要怎么测试&#…

马斯克震撼演讲:我想创立一个新世界

目录 1拼多多杀入大模型领域&#xff1a;年薪百万招聘人才 2马斯克震撼演讲&#xff1a;我想创立一个新世界 3文心4.0上线首交答卷&#xff1a;百度2023Q3成色如何 1拼多多杀入大模型领域&#xff1a;年薪百万招聘人才 快科技11月22日消息&#xff0c;据国内媒体报道&#x…

解决ESP32内部RAM内存不足的问题

一&#xff0c;为什么需要外部RAM ESP32有520kB的内部RAM空间可以使用&#xff0c;这对于一般的情况是够用的&#xff0c;但是如果设备需要涉及音频或者显示图像等处理时&#xff0c;需要更大的内存空间来处理这些数据。ESP32支持扩展外部RAM&#xff0c;其实乐鑫已经在其ESP32…

2020年计网408

第33题 下图描述的协议要素是&#xff08; &#xff09;。I. 语法 II. 语义 III. 时序 A. 仅 I B. 仅 II C. 仅 III D. I、II 和 III 本题考察网络协议三要素的相关知识。 网络协议的三要素分别是语法、语义、同步&#xff08;时序&#xff09;。语法&#xff1a;定义收发双…

【PyGIS】使用阿里AIEarth快速下载指定区域指定年份的土地利用数据

说明 中国逐年土地覆盖数据集(CLCD) 由武汉大学的杨杰和黄昕教授团队基于Landsat影像制作了中国逐年土地覆盖数据集(annual China Land Cover Dataset, CLCD),数据包含1985—2021年中国逐年土地覆盖信息。研究团队基于Landsat长时序卫星观测数据,构建时空特征,结合随机森…

lombok 引入

lombok 依赖--><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></dependency>

智能车入门补充篇——电感值处理、转向控制与巡线

冒泡法 冒泡法是一种简单的排序算法&#xff0c;它重复地遍历要排序的数列&#xff0c;一次比较两个元素&#xff0c;如果它们的顺序错误就把它们交换过来。遍历数列的工作是重复地进行直到没有再需要交换&#xff0c;也就是说该数列已经排序完成。冒泡排序的时间复杂度为O(n^…

国内怎么投资黄金,炒黄金有哪些好方法?

随着我国综合实力的不断强大&#xff0c;投资市场的发展也日臻完善&#xff0c;现已成为了国际黄金市场的重要组成部分&#xff0c;人们想要精准判断金市走向&#xff0c;就离不开对我国经济等信息的仔细分析。而想要有效提升盈利概率&#xff0c;人们还需要掌握国内黄金投资的…

centos无法进入系统之原因解决办法集合

前言 可爱的小伙伴们&#xff0c;由于精力有限&#xff0c;暂时整理了两类。如果没有你遇到的问题也没有关系&#xff0c;欢迎底下留言评论或私信&#xff0c;小编看到后第一时间帮助解决 一. Centos 7 LVM xfs文件系统修复 情况1&#xff1a; [sda] Assuming drive cache:…

Docker Swarm总结(2/3)

目录 8、service 操作 8.1 task 伸缩 8.2 task 容错 8.3 服务删除 8.4 滚动更新 8.5 更新回滚 9、service 全局部署模式 9.1 环境变更 9.2 创建 service 9.3 task 伸缩 10、overlay 网络 10.1 测试环境 1搭建 10.2 overlay 网络概述 10.3 docker_gwbridg 网络基础…

​极氪,中国传统汽车品牌电动化的样板间

这篇文章早就想写了&#xff0c;因为太忙的原因就一直跳票&#xff0c;正好最近两件事的出现&#xff0c;又触发了想写这篇文章的冲动。 两件事主要是&#xff1a; 一&#xff0c;10 月份各家陆续公布了单月销量以及累计销量&#xff1b; 二&#xff0c;极氪在北京正式发布了 …

算法刷题-动态规划-1

算法刷题-动态规划-1 不同路径不同路径||方法一&#xff1a;方法二 第N个泰波那契数递归写法滚动数组 三步问题递归操作滚动数组 使用最小画法爬楼梯递归 解码方法方法一方法二&#xff1a;&#xff08;大佬讲解&#xff09; 不同路径 //机器人不同的路径进入到指定的地点 publ…

OSG文字-渐变文字(4)

渐变文字(osgText::FadeText类)继承自osgText::Text类继承关系图如图9-6所示 图9-6 osgText::FadeText的继承关系图 从继承关系图中可以看出&#xff0c;它继承自osgText::Text类&#xff0c;因此&#xff0c;它具备一般文字属性的设置方法这里不再重复说明。创建渐变文字与一般…

【JavaEE】Spring更简单的存储和获取对象(类注解、方法注解、属性注入、Setter注入、构造方法注入)

一、存储Bean对象 在这篇文章中我介绍了Spring最简单的创建和使用&#xff1a;Spring的创建和使用 其中存储Bean对象是这样的&#xff1a; 1.1 配置扫描路径 想要成功把对象存到Spring中&#xff0c;我们需要配置对象的扫描包路径 这样的话&#xff0c;就只有被配置了的包…

详解Python中哈希表的使用。站在开发者角度,与大家一起探究哈希的世界。

文章目录 1. 前言2. 哈希表2.1 哈希函数2.2 哈希算法2.3 常见哈希算法2.4 哈希冲突 3.总结关于Python技术储备一、Python所有方向的学习路线二、Python基础学习视频三、精品Python学习书籍四、Python工具包项目源码合集①Python工具包②Python实战案例③Python小游戏源码五、面…

【数据库】数据库中的备份与恢复,保障容灾时的数据一致性与完整性

数据库的备份机制 ​专栏内容&#xff1a; 手写数据库toadb 本专栏主要介绍如何从零开发&#xff0c;开发的步骤&#xff0c;以及开发过程中的涉及的原理&#xff0c;遇到的问题等&#xff0c;让大家能跟上并且可以一起开发&#xff0c;让每个需要的人成为参与者。 本专栏会定期…

【LeetCode刷题】-- 29.两数相除

29.两数相除 思路&#xff1a; class Solution {public int divide(int dividend, int divisor) {//考察被除数为最小值的情况if(dividend Integer.MIN_VALUE){//被除数为最小值&#xff0c;除数是1&#xff0c;返回最小值if(divisor 1){return Integer.MIN_VALUE;}//除数是-…