赞
踩
setup
函数是一个组件选项,在创建组件之前执行,一旦 props 被解析,并作组合式 API 的入口。
setup
选项是一个接收 props
和 context
的函数。此外,我们将 setup
返回的所有内容都暴露给组件的其余部分 (计算属性、方法、生命周期钩子等等) 以及组件的模板。
- <script>
- // 这是一个基于 TypeScript 的 Vue 组件
- import { defineComponent } from 'vue'
- export default defineComponent({
- setup(props, context) {
- // 在这里声明数据,或者编写函数并在这里执行它
- return {
- // 需要给 `<template />` 用的数据或函数,在这里 `return` 出去
- }
- },
- })
- </script>
新的 setup
选项是在组件创建之前, props
被解析之后执行,是组合式 API 的入口。
在添加了setup的script标签中,组件只需引入不用注册,属性和方法也不用返回,也不用写
setup
函数,也不用写export default
,甚至是自定义指令也可以在我们的template
中自动获得。
tip:在 setup
中应该避免使用 this
,因为它不会找到组件实例。
- <script setup>
-
- ...
-
- </script>
要注意的是 "暴露给模板" 不同于 "暴露给外部”
TIP:在使用 Vue 3 生命周期的情况下,整个组件相关的业务代码,都可以放在 setup
里执行。
因为在 setup
之后,其他的生命周期才会被启用.
对比Vue2、Vue3生命周期变化
Vue 2 生命周期 | Vue 3 生命周期 | 执行时间说明 |
beforeCreate | setup | 组件创建前执行 |
created | setup | 组件创建后执行 |
beforeMount | onBeforeMount | 组件挂载到节点上之前执行 |
mounted | onMounted | 组件挂载完成后执行 |
beforeUpdate | onBeforeUpdate | 组件更新之前执行 |
updated | onUpdated | 组件更新完成之后执行 |
beforeDestroy | onBeforeUnmount | 组件卸载之前执行 |
destroyed | onUnmounted | 组件卸载完成后执行 |
errorCaptured | onErrorCaptured | 当捕获一个来自子孙组件的异常时激活钩子函数 |
可以看到 Vue 2 生命周期里的 beforeCreate
和 created
,在 Vue 3 里已被 setup
替代。
它是 Vue3 的一个新语法糖,在 setup
函数中,所有 ES 模块导出都被认为是暴露给上下文的值,并包含在 setup() 返回对象中。相对之前的写法,语法更简单。
1.<script setup>
语法糖并不是新增的功能模块,它只是简化了以往的组合API的必须返回(return)的写法,并且有更好的运行时性能。
2.在 setup 函数中:所有 ES 模块导出都被认为是暴露给上下文的值,并包含在 setup() 返回对象中。
使用方式:在 script 标签加上 setup 关键字即可
- <template>
- <div class="home">
- 值:{{flag }}
- <button @click="change">修改值</button>
- </div>
- </template>
-
- <!-- 只需要在script上添加setup -->
- <script lang="ts" setup>
-
- import { ref } from 'vue';
-
- <!-- flag变量不需要在 return出去了 -->
- let flag=ref("啦啊啦啦啦啦")
-
- <!-- 函数也可以直接引用,不用在return中返回 -->
- let change=():void=>{
- flag.value='略略略略略略略略'
- }
-
- </script>
在 script setup 中,引入的组件可以直接使用,无需再通过components进行注册,并且无法指定当前组件的名字,它会自动以文件名为主,也就是不用再写name属性了。
示例:
- <template>
- <div class="home">
- <test-com></test-com>
- </div>
- </template>
-
- <script lang="ts" setup>
-
- // 组件命名采用的是大驼峰,引入后不需要在注册
- // 在使用的使用直接是小写和横杠的方式连接 test-com
- import TestCom from "../components/TestCom.vue"
-
- </script>
不需要使用setup
函数,那么子组件怎么接受父组件传递过来的值呢?props,emit怎么获取呢?
当当当当!defineProps
defineProps
defineProps ----> [用来接收父组件传来的 props]
通过defineProps
指定当前 props 类型,获得上下文的props对象。
示例:
- <template>
- <div class="box">
- <test-com :info="msg" time="42分钟"></test-com>
- </div>
- </template>
-
- <script lang="ts" setup>
- import TestCom from "../components/TestCom.vue"
- let msg='今天是2023年3月14日'
-
- </script>
- <template>
- <div>
- <h2> 啦啦啦啦啦啦啦啦</h2>
- <p>信息: {{ info}}</p>
- <p> {{ time }}</p>
- </div>
- </template>
-
- <script lang="ts" setup>
-
- import {defineProps} from 'vue'
-
- defineProps({
- info:{
- type:String,
- default:'----'
- },
- time:{
- type:String,
- default:'0分钟'
- },
- })
-
- </script>
2.defineEmits
defineEmit ----> [子组件向父组件事件传递]
使用defineEmit
定义当前组件含有的事件,并通过返回的上下文去执行 emit。
代码示列:
- <script setup>
- import { defineEmits } from 'vue'
- const emit = defineEmits(['change', 'delete'])
-
- </script>
defineProps 用来接收父组件传来的 props ; defineEmits 用来声明触发的事件。
父组件
- //父组件
- <template>
- //监听子组件的getChild方法,传msg给子组件
- <Child @getChild="getChild" :title="msg" />
- </template>
-
- <script setup>
- import { ref } from 'vue'
- import Child from '@/components/Child.vue'
- const msg = ref('parent value')
-
- const getChild = (e) => {
- // 接收父组件传递过来的数据
- console.log(e); // child value
- }
- </script>
子组件
- //子组件
- <template>
- <div @click="toEmits">Child Components</div>
- </template>
-
- <script setup>
- // defineEmits,defineProps无需导入,直接使用
- const emits = defineEmits(['getChild']);
- //接收父组件传来的props
- const props = defineProps({
- title: {
- type: String,
- defaule: 'defaule title'
- }
- });
- const toEmits = () => {
- // 向父组件抛出带参事件getChild(其中参数是child value)
- emits('getChild', 'child value')
- }
- // 获取父组件传递过来的数据
- console.log(props.title); // parent value
- </script>
四.useSlots()
和 useAttrs()
获取 slots 和 attrs
useAttrs
:这是用来获取 attrs 数据,但是这和 vue2 不同,里面包含了 class
、属性
、方法
。- <template>
- <component v-bind='attrs'></component>
- </template>
- <srcipt setup lang='ts'>
- const attrs = useAttrs();
- <script>
useSlots
: 顾名思义,获取插槽数据。使用示例:
- // 旧
- <script setup>
- import { useContext } from 'vue'
- const { slots, attrs } = useContext()
- </script>
-
- // 新
- <script setup>
- import { useAttrs, useSlots } from 'vue'
- const attrs = useAttrs()
- const slots = useSlots()
- </script>
defineExpose ----> [组件暴露出自己的属性]
传统的写法,我们可以在父组件中,通过 ref 实例的方式去访问子组件的内容,但在 script setup 中,该方法就不能用了,setup 相当于是一个闭包,除了内部的 template
模板,谁都不能访问内部的数据和方法。
<script setup>
的组件默认不会对外部暴露任何内部声明的属性。如果有部分属性要暴露出去,可以使用
defineExpose
如果需要对外暴露 setup 中的数据和方法,需要使用 defineExpose API。
tip:// defineExpose无需导入,直接使用
示例:
子组件
- //子组件
- <template>
- {{msg}}
- </template>
-
- <script setup>
- import { ref } from 'vue'
- let msg = ref("Child Components");
- let num = ref(123);
- defineExpose({
- msg,
- num
- });
- </script>
父组件
- //父组件
- <template>
- <Child ref="child" />
- </template>
-
- <script setup>
- import { ref, onMounted } from 'vue'
- import Child from '@/components/Child.vue'
- let child = ref(null);
- onMounted(() => {
- console.log(child.value.msg); // Child Components
- console.log(child.value.num); // 123
- })
- </script>
v-memod
会记住一个模板的子树,元素和组件上都可以使用。
该指令接收一个固定长度的数组作为依赖值进行“记忆比对”。如果数组中的每个值都和上次渲染的时候相同,则整个子树的更新会被跳过。
即使是虚拟 DOM 的 VNode 创建也将被跳过,因为子树的记忆副本可以被重用。
因此渲染的速度会非常的快。
tip:正确地声明记忆数组是很重要。
开发者有责任指定正确的依赖数组,以避免必要的更新被跳过。
- <li v-for="item in listArr" :key="item.id" v-memo="['valueA','valueB']">
- {{ item.name }}
- </li>
v-memod
的指令使用较少,它的作用是:缓存模板中的一部分数据。
只创建一次,以后就不会再更新了。也就是说用内存换取时间。
例:style v-bind
将span
变成红色
- <template>
- <span> 啦啦啦啦啦啦啦啦啦啦 </span>
- </template>
-
- <script setup>
- import { reactive } from 'vue'
- const state = reactive({
- color: 'red'
- })
- </script>
- <style scoped>
- span {
- /* 使用v-bind绑定state中的变量 */
- color: v-bind('state.color');
- }
- </style>
配置项的缺失,有时候我们需要更改组件选项,在setup
中我们目前是无法做到的。我们需要在上方
再引入一个 script
,在上方写入对应的 export
即可,需要单开一个 script。
<script setup>
可以和普通的 <script>
一起使用。
普通的 <script>
在有这些需要的情况下或许会被使用到:
<script setup>
声明的选项,例如 inheritAttrs
或通过插件启用的自定义的选项。在script setup 外使用export default,其内容会被处理后放入原组件声明字段。
- <script>
- // 普通 `<script>`, 在模块范围下执行(只执行一次)
- runSideEffectOnce()
- // 声明额外的选项
- export default {
- name: "MyComponent",
- inheritAttrs: false,
- customOptions: {}
- }
- </script>
- <script setup>
- import HelloWorld from '../components/HelloWorld.vue'
- // 在 setup() 作用域中执行 (对每个实例皆如此)
-
- </script>
- <template>
- <div>
- <HelloWorld msg="Vue3 + TypeScript + Vite"/>
- </div>
- </template>
注意:Vue 3 SFC 一般会自动从组件的文件名推断出组件的 name。在大多数情况下,不需要明确的 name 声明。唯一需要的情况是当你需要
<keep-alive>
包含或排除或直接检查组件的选项时,你需要这个名字。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。