当前位置:   article > 正文

学习script setup 语法糖

script setup

首先讲解组合式API:setup()

setup 函数是一个组件选项,在创建组件之前执行,一旦 props 被解析,并作组合式 API 的入口。

BEFORE

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

  1. <script>
  2. // 这是一个基于 TypeScript 的 Vue 组件
  3. import { defineComponent } from 'vue'
  4. export default defineComponent({
  5. setup(props, context) {
  6. // 在这里声明数据,或者编写函数并在这里执行它
  7. return {
  8. // 需要给 `<template />` 用的数据或函数,在这里 `return` 出去
  9. }
  10. },
  11. })
  12. </script>

NOW 

新的 setup 选项是在组件创建之前, props 被解析之后执行,是组合式 API 的入口。

在添加了setup的script标签中,组件只需引入不用注册,属性和方法也不用返回,也不用写setup函数,也不用写export default,甚至是自定义指令也可以在我们的template中自动获得。

tip:在 setup 中应该避免使用 this,因为它不会找到组件实例。

  1. <script setup>
  2. ...
  3. </script>

要注意的是 "暴露给模板" 不同于 "暴露给外部

TIP:在使用 Vue 3 生命周期的情况下,整个组件相关的业务代码,都可以放在 setup 里执行。

因为在 setup 之后,其他的生命周期才会被启用.

对比Vue2、Vue3生命周期变化

组件生命周期

Vue 2 生命周期Vue 3 生命周期执行时间说明
beforeCreatesetup组件创建前执行
createdsetup组件创建后执行
beforeMountonBeforeMount组件挂载到节点上之前执行
mountedonMounted组件挂载完成后执行
beforeUpdateonBeforeUpdate组件更新之前执行
updatedonUpdated组件更新完成之后执行
beforeDestroyonBeforeUnmount组件卸载之前执行
destroyedonUnmounted组件卸载完成后执行
errorCapturedonErrorCaptured当捕获一个来自子孙组件的异常时激活钩子函数

可以看到 Vue 2 生命周期里的 beforeCreatecreated ,在 Vue 3 里已被 setup 替代。


script setup 语法糖

它是 Vue3 的一个新语法糖,在 setup 函数中,所有 ES 模块导出都被认为是暴露给上下文的值,并包含在 setup() 返回对象中。相对之前的写法,语法更简单。

一、自动注册属性和方法无需返回,直接使用

1.<script setup> 语法糖并不是新增的功能模块,它只是简化了以往的组合API的必须返回(return)的写法,并且有更好的运行时性能

2.在 setup 函数中:所有 ES 模块导出都被认为是暴露给上下文的值,并包含在 setup() 返回对象中。

使用方式:在 script 标签加上 setup 关键字即可

  1. <template>
  2.   <div class="home">
  3.     值:{{flag }}
  4.     <button @click="change">修改值</button>
  5.   </div>
  6. </template>
  7. <!-- 只需要在script上添加setup -->
  8. <script lang="ts" setup>
  9.     import { ref } from 'vue';
  10.     <!-- flag变量不需要在 return出去了 -->
  11.     let flag=ref("啦啊啦啦啦啦")
  12.     <!-- 函数也可以直接引用,不用在return中返回 -->
  13.     let change=():void=>{
  14.         flag.value='略略略略略略略略'
  15.     }
  16. </script>

 

二.组件自动注册

在 script setup 中,引入的组件可以直接使用,无需再通过components进行注册,并且无法指定当前组件的名字,它会自动以文件名为主,也就是不用再写name属性了。

示例

  1. <template>
  2.   <div class="home">
  3.     <test-com></test-com>
  4.   </div>
  5. </template>
  6. <script lang="ts" setup>
  7. // 组件命名采用的是大驼峰,引入后不需要在注册
  8. // 在使用的使用直接是小写和横杠的方式连接 test-com
  9. import TestCom from "../components/TestCom.vue"
  10. </script>

 

三.defineProps 和 defineEmits

不需要使用setup函数,那么子组件怎么接受父组件传递过来的值呢?props,emit怎么获取呢?

当当当当!defineProps

1.defineProps

defineProps ----> [用来接收父组件传来的 props]

通过defineProps指定当前 props 类型,获得上下文的props对象。

示例:

父组件传递参数:

  1. <template>
  2.   <div class="box">
  3.     <test-com :info="msg" time="42分钟"></test-com>
  4.   </div>
  5. </template>
  6. <script lang="ts" setup>
  7. import TestCom from "../components/TestCom.vue"
  8. let msg='今天是2023年3月14日'
  9. </script>

子组件接受参数:

  1. <template>
  2.     <div>
  3.         <h2> 啦啦啦啦啦啦啦啦</h2>
  4.         <p>信息: {{ info}}</p>
  5.         <p> {{ time }}</p>
  6.     </div>
  7. </template>
  8. <script lang="ts" setup>
  9. import {defineProps} from 'vue'
  10. defineProps({
  11.     info:{
  12.         type:String,
  13.         default:'----'
  14.     },
  15.     time:{
  16.         type:String,
  17.         default:'0分钟'
  18.     },
  19. })
  20. </script>

解决了父组件向子组件传值,那么子组件怎么向父组件抛出事件?

2.defineEmits

定义 emit

defineEmit ----> [子组件向父组件事件传递]

使用defineEmit定义当前组件含有的事件,并通过返回的上下文去执行 emit。

代码示列

  1. <script setup>
  2. import { defineEmits } from 'vue'
  3. const emit = defineEmits(['change', 'delete'])
  4. </script>

父子组件通信

defineProps 用来接收父组件传来的 props ; defineEmits 用来声明触发的事件。

父组件

  1. //父组件
  2. <template>
  3. //监听子组件的getChild方法,传msg给子组件
  4. <Child @getChild="getChild" :title="msg" />
  5. </template>
  6. <script setup>
  7. import { ref } from 'vue'
  8. import Child from '@/components/Child.vue'
  9. const msg = ref('parent value')
  10. const getChild = (e) => {
  11. // 接收父组件传递过来的数据
  12. console.log(e); // child value
  13. }
  14. </script>

 子组件

  1. //子组件
  2. <template>
  3. <div @click="toEmits">Child Components</div>
  4. </template>
  5. <script setup>
  6. // defineEmits,defineProps无需导入,直接使用
  7. const emits = defineEmits(['getChild']);
  8. //接收父组件传来的props
  9. const props = defineProps({
  10. title: {
  11. type: String,
  12. defaule: 'defaule title'
  13. }
  14. });
  15. const toEmits = () => {
  16. // 向父组件抛出带参事件getChild(其中参数是child value)
  17. emits('getChild', 'child value')
  18. }
  19. // 获取父组件传递过来的数据
  20. console.log(props.title); // parent value
  21. </script>
  • 子组件通过 defineProps 接收父组件传过来的数据
  • 子组件通过 defineEmits 定义事件发送信息给父组件

四.useSlots()useAttrs()

获取 slots 和 attrs

  1. useAttrs:这是用来获取 attrs 数据,但是这和 vue2 不同,里面包含了 class属性方法
  1. <template>
  2. <component v-bind='attrs'></component>
  3. </template>
  4. <srcipt setup lang='ts'>
  5. const attrs = useAttrs();
  6. <script>
  1. useSlots: 顾名思义,获取插槽数据。

使用示例:

  1. // 旧
  2. <script setup>
  3. import { useContext } from 'vue'
  4. const { slots, attrs } = useContext()
  5. </script>
  6. // 新
  7. <script setup>
  8. import { useAttrs, useSlots } from 'vue'
  9. const attrs = useAttrs()
  10. const slots = useSlots()
  11. </script>

五.defineExpose API

defineExpose ----> [组件暴露出自己的属性]

传统的写法,我们可以在父组件中,通过 ref 实例的方式去访问子组件的内容,但在 script setup 中,该方法就不能用了,setup 相当于是一个闭包,除了内部的 template模板,谁都不能访问内部的数据和方法。

<script setup> 的组件默认不会对外部暴露任何内部声明的属性。

如果有部分属性要暴露出去,可以使用 defineExpose

如果需要对外暴露 setup 中的数据和方法,需要使用 defineExpose API。

tip:// defineExpose无需导入,直接使用

示例

子组件

  1. //子组件
  2. <template>
  3. {{msg}}
  4. </template>
  5. <script setup>
  6. import { ref } from 'vue'
  7. let msg = ref("Child Components");
  8. let num = ref(123);
  9. defineExpose({
  10. msg,
  11. num
  12. });
  13. </script>

父组件

  1. //父组件
  2. <template>
  3. <Child ref="child" />
  4. </template>
  5. <script setup>
  6. import { ref, onMounted } from 'vue'
  7. import Child from '@/components/Child.vue'
  8. let child = ref(null);
  9. onMounted(() => {
  10. console.log(child.value.msg); // Child Components
  11. console.log(child.value.num); // 123
  12. })
  13. </script>

六.新增指令 v-memo

v-memod会记住一个模板的子树,元素和组件上都可以使用。

该指令接收一个固定长度的数组作为依赖值进行“记忆比对”。如果数组中的每个值都和上次渲染的时候相同,则整个子树的更新会被跳过。

即使是虚拟 DOM 的 VNode 创建也将被跳过,因为子树的记忆副本可以被重用。

因此渲染的速度会非常的快。

tip:正确地声明记忆数组是很重要。

开发者有责任指定正确的依赖数组,以避免必要的更新被跳过。

  1. <li v-for="item in listArr"  :key="item.id"  v-memo="['valueA','valueB']">
  2.     {{ item.name   }}
  3. </li>

v-memod的指令使用较少,它的作用是:缓存模板中的一部分数据。

只创建一次,以后就不会再更新了。也就是说用内存换取时间。


七.style v-bind 

例:style v-bindspan变成红色

  1. <template>
  2.   <span> 啦啦啦啦啦啦啦啦啦啦 </span>  
  3. </template>
  4. <script setup>
  5.   import { reactive } from 'vue'
  6.   const state = reactive({
  7.     color'red'
  8.   })
  9. </script>
  10. <style scoped>
  11.   span {
  12.     /* 使用v-bind绑定state中的变量 */
  13.     colorv-bind('state.color');
  14.   }  
  15. </style>

八.定义组件其他配置

配置项的缺失,有时候我们需要更改组件选项,在setup中我们目前是无法做到的。我们需要在上方再引入一个 script,在上方写入对应的 export即可,需要单开一个 script。

<script setup> 可以和普通的 <script> 一起使用。

普通的 <script> 在有这些需要的情况下或许会被使用到:

  • 无法在 <script setup> 声明的选项,例如 inheritAttrs 或通过插件启用的自定义的选项。
  • 声明命名导出。
  • 运行副作用或者创建只需要执行一次的对象。

在script setup 外使用export default,其内容会被处理后放入原组件声明字段。

  1. <script>
  2. // 普通 `<script>`, 在模块范围下执行(只执行一次)
  3. runSideEffectOnce()
  4. // 声明额外的选项
  5. export default {
  6. name: "MyComponent",
  7. inheritAttrs: false,
  8. customOptions: {}
  9. }
  10. </script>
  11. <script setup>
  12. import HelloWorld from '../components/HelloWorld.vue'
  13. // 在 setup() 作用域中执行 (对每个实例皆如此)
  14. </script>
  15. <template>
  16. <div>
  17. <HelloWorld msg="Vue3 + TypeScript + Vite"/>
  18. </div>
  19. </template>

注意:Vue 3 SFC 一般会自动从组件的文件名推断出组件的 name。在大多数情况下,不需要明确的 name 声明。唯一需要的情况是当你需要 <keep-alive> 包含或排除或直接检查组件的选项时,你需要这个名字。


 

参考文章:https://juejin.cn/post/7209872710155206717 

Vue3 script setup 语法糖-阿里云开发者社区 (aliyun.com)

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/我家自动化/article/detail/172831
推荐阅读
  

闽ICP备14008679号