vue 3.2 的 script setup 语法_前端精髓的博客-程序员秘密

技术标签: 1024程序员节  JavaScript  

vue 3.2 已经正式支持 <script setup> 语法,并且现在就可以在生产环境下使用了,接下开始学习基本用法。

<script setup> 是在单文件组件 (SFC) 中使用组合式 API 的编译时语法糖。相比于普通的 <script> 语法,它具有更多优势:

  1. 更少的样板内容,更简洁的代码。
  2. 能够使用纯 Typescript 声明 props 和抛出事件。
  3. 更好的运行时性能 (其模板会被编译成与其同一作用域的渲染函数,没有任何的中间代理)。
  4. 更好的 IDE 类型推断性能 (减少语言服务器从代码中抽离类型的工作)。

基本语法

要使用这个语法,需要将 setup attribute 添加到 <script> 代码块上:

<script setup>
console.log('hello script setup')
</script>

里面的代码会被编译成组件 setup() 函数的内容。这意味着与普通的 <script> 只在组件被首次引入的时候执行一次不同,<script setup> 中的代码会在每次组件实例被创建的时候执行。

顶层的绑定会被暴露给模板

当使用 <script setup> 的时候,任何在 <script setup> 声明的顶层的绑定 (包括变量,函数声明,以及 import 引入的内容) 都能在模板中直接使用:

<script setup>
// 变量
const msg = 'Hello!'

// 函数
function log() {
    
  console.log(msg)
}
</script>

<template>
  <div @click="log">{
    {
     msg }}</div>
</template>

import 导入的内容也会以同样的方式暴露。意味着可以在模板表达式中直接使用导入的 helper 函数,并不需要通过 methods 选项来暴露它:

<script setup>
import {
     capitalize } from './helpers'
</script>

<template>
  <div>{
    {
     capitalize('hello') }}</div>
</template>

响应式

响应式状态需要明确使用响应式 APIs 来创建。和从 setup() 函数中返回值一样,ref 值在模板中使用的时候会自动解包:

<script setup>
import {
     ref } from 'vue'

const count = ref(0)
</script>

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

使用组件

<script setup> 范围里的值也能被直接作为自定义组件的标签名使用:

<script setup>
import MyComponent from './MyComponent.vue'
</script>

<template>
  <MyComponent />
</template>

将 MyComponent 看做被一个变量所引用。

动态组件

由于组件被引用为变量而不是作为字符串键来注册的,在 <script setup> 中要使用动态组件的时候,就应该使用动态的 :is 来绑定:

<script setup>
import Foo from './Foo.vue'
import Bar from './Bar.vue'
</script>

<template>
  <component :is="Foo" />
  <component :is="someCondition ? Foo : Bar" />
</template>

请注意组件是如何在三元表达式中被当做变量使用的。

递归组件

一个单文件组件可以通过它的文件名被其自己所引用。例如:名为 FooBar.vue 的组件可以在其模板中用 <FooBar/> 引用它自己。

请注意这种方式相比于 import 导入的组件优先级更低。如果有命名的 import 导入和组件的推断名冲突了,可以使用 import 别名导入:

import {
     FooBar as FooBarChild } from './components'

命名空间组件

可以使用带点的组件标记,例如 <Foo.Bar> 来引用嵌套在对象属性中的组件。这在需要从单个文件中导入多个组件的时候非常有用:

<script setup>
import * as Form from './form-components'
</script>

<template>
  <Form.Input>
    <Form.Label>label</Form.Label>
  </Form.Input>
</template>

defineProps 和 defineEmits

<script setup> 中必须使用 definePropsdefineEmits API 来声明 props 和 emits ,它们具备完整的类型推断并且在 <script setup> 中是直接可用的:

<script setup>
const props = defineProps({
    
  foo: String
})

const emit = defineEmits(['change', 'delete'])
// setup code
</script>

definePropsdefineEmits 都是只在 <script setup> 中才能使用的编译器宏。他们不需要导入且会随着 <script setup> 处理过程一同被编译掉。

defineProps 接收与 props 选项相同的值,defineEmits 也接收 emits 选项相同的值。

definePropsdefineEmits 在选项传入后,会提供恰当的类型推断。

传入到 definePropsdefineEmits 的选项会从 setup 中提升到模块的范围。因此,传入的选项不能引用在 setup 范围中声明的局部变量。这样做会引起编译错误。但是,它可以引用导入的绑定,因为它们也在模块范围内。

如果使用了 Typescript,使用纯类型声明来声明 prop 和 emits 也是可以的。

defineExpose

使用 <script setup> 的组件是默认关闭的,也即通过模板 ref 或者 $parent 链获取到的组件的公开实例,不会暴露任何在 <script setup> 中声明的绑定。

为了在 <script setup> 组件中明确要暴露出去的属性,使用 defineExpose 编译器宏:

<script setup>
import {
     ref } from 'vue'

const a = 1
const b = ref(2)

defineExpose({
    
  a,
  b
})
</script>

当父组件通过模板 ref 的方式获取到当前组件的实例,获取到的实例会像这样 { a: number, b: number } (ref 会和在普通实例中一样被自动解包)

useSlots 和 useAttrs

<script setup> 使用 slots 和 attrs 的情况应该是很罕见的,因为可以在模板中通过 $slots$attrs 来访问它们。在你的确需要使用它们的罕见场景中,可以分别用 useSlotsuseAttrs 两个辅助函数:

<script setup>
import {
     useSlots, useAttrs } from 'vue'

const slots = useSlots()
const attrs = useAttrs()
</script>

useSlotsuseAttrs 是真实的运行时函数,它会返回与 setupContext.slotssetupContext.attrs 等价的值,同样也能在普通的组合式 API 中使用。

与普通的 script 一起使用

<script setup> 可以和普通的 <script> 一起使用。普通的 <script> 在有这些需要的情况下或许会被使用到:

  1. 无法在 <script setup> 声明的选项,例如 inheritAttrs 或通过插件启用的自定义的选项。
  2. 声明命名导出。
  3. 运行副作用或者创建只需要执行一次的对象。
<script>
// 普通 <script>, 在模块范围下执行(只执行一次)
runSideEffectOnce()

// 声明额外的选项
export default {
    
  inheritAttrs: false,
  customOptions: {
    }
}
</script>

<script setup>
// 在 setup() 作用域中执行 (对每个实例皆如此)
</script>

顶层 await

<script setup> 中可以使用顶层 await。结果代码会被编译成 async setup()

<script setup>
const post = await fetch(`/api/post/1`).then(r => r.json())
</script>

另外,await 的表达式会自动编译成在 await 之后保留当前组件实例上下文的格式。

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/wu_xianqiang/article/details/120939405

智能推荐

《Oracle系列》Oracle创建Schema、用户名及表空间_DATA数据猿的博客-程序员秘密

2 查看当前表空间3 创建表空间spacename : 是自定义的表空间名字,当然也是新的Schema的名称filedir : 文件存储路径,可随意选择一个磁盘空间充足的目录4 将空间分配给用户5 给用户授权6 查看表空间7 连接

[4G+5G专题-144]: 一体化小基站- 5G小基站硬件建议架构概述_5g一体化站需求分析_文火冰糖的硅基工坊的博客-程序员秘密

作者主页(文火冰糖的硅基工坊):文火冰糖(王文兵)的博客_文火冰糖的硅基工坊_程序员秘密本文网址:目录第1章 硬件总体架构1.1 架构图1.2 功能模块1.3 接口1.4 主要指标第2章 时钟同步硬件架构第1章 硬件总体架构1.1 架构图1.2 功能模块(1)Ethbackhaul 1G和10G接口(2)NPU (ARM)OAM管理 TRSW传输 BBU L3 BBU L2 BBU MAC调度(3)BBU L1 (DSP SOC)

BuilderException: Error parsing SQL Mapper Configuration. Cause: java.lang.IllegalArgumentException:_nickkkkkkkkk的博客-程序员秘密

问题org.apache.ibatis.exceptions.PersistenceException: ### Error building SqlSession.### The error may exist in com/wei/mapper/UserMapper.xml### The error occurred while processing mapper_resultMap[userAccountMap]### Cause: org.apache.ibatis.builder.Bui

洛谷P2242 公路维修问题(Road)_dezhen7015的博客-程序员秘密

题目描述在一个夜黑风高,下着暴风雨的夜晚,farmer John的牛棚的屋顶、门被吹飞了。 好在许多牛正在度假,所以牛棚没有住满。 牛棚一个紧挨着另一个被排成一行,牛就住在里面过夜。 有些牛棚里有牛,有些没有。 所有的牛棚有相同的宽度。 自门遗失以后,farmer John必须尽快在牛棚之前竖立起新的木板。 他的新木材供应商将会供应他任何他想要的长度,但是吝啬的供应商只能提供有限数目...

Android中自定义View、ViewGroup理论基础详解_孙群的博客-程序员秘密

Android自身提供了许多widgets,但是有时候这些widgets并不能满足我们的需求,这时我们就需要自定义View,本文会详细说明自定义View的各种理论基础,只有理解了这些知识,我们才能更好地实现各种功能的控件。我觉得自定义View中最重要的部分就是绘图和交互,自定义的绘图使得你的View与众不同,交互使用户可以与你的View进行交互,而绘图的前提是View的量算与布局,交互的基础是触摸事

随便推点

在web项目中使用MarkDown组件_markdown web_布碗的博客-程序员秘密

说 在项目中,要录入图文信息,需要将图片存到服务器。本篇博文将介绍在javaweb项目中,怎样使用MarkDown组件。在项目中使用了servlet,smartupload进行文件的上传。

QFIL软件烧写镜像_weixin_30621959的博客-程序员秘密

1、准备好需要烧写的文件烧写之前,需要先准备好需要的文件,如下:2、打开QFIL程序接下来运行QFIL程序,如下:3、选择端口程序运行后,选择合适的端口,如下:点击端口选择,然后选择Port:4、选择Flat Build模式在软件中选择Flat Build模式,并选择编程文件和需要烧写的文件路径:5、开...

隐藏cmd窗口(.bat .vbs)_vbs隐藏cmd窗口_灬囖的博客-程序员秘密

转载自批处理隐藏自身窗口大多数时候,使用批处理执行一些任务。但是批处理的黑色命令窗口会一直存在很烦人。可以通过两种方式,隐藏bat脚本。方法1:直接在 bat 文件最前边加上以下内容:[plain] view plain copy print?  [plain] view plain copy [email protected] off       if ”%1” == “h” goto begin

c++ 用穷举法输入1-100的素数。_穷举法输出100以内的素数_菩提树下的呆子的博客-程序员秘密

#include &lt;iostream&gt;using namespace std;//1.用穷举法输入1-100的素数。int main(){ for(int i =0;i&lt;=100;i++){ int j =0; for(j=2;j&lt;i;j++){ if(i%j==0){ break; } } if(i==j){

python之文件处理_python中文件处理offset为负数_CaughyHU的博客-程序员秘密

#一、文件本身的处理1.打开文件open(file, mode='r', buffering=None, encoding=None, errors=None, newline=None, closefd=True)file: 必需,文件路径(相对或者绝对路径)。mode: 可选,文件打开模式buffering: 设置缓冲encoding: 一般使用utf8errors: 报错级别newline: 区分换行符打开模式执行操作‘r’以只读方式打开文件。文件的指针将会放

Postman使用全局变量出现全局变量更新后是灰色并被横线划掉,无法调用_postman websocket 灰色_羲義的博客-程序员秘密

本人在测试一个项目中登录需要获取token值并把值作为接下来操作的验签,然后就想做个全局变量让其他接口直接调用。然后就开始先写了获取token接口:然后开始写获取token的脚本很简单:可以Ctrl+Alt+C控制台验证一直是否获取到了token值;然后在 Environment quick look中设置了全局变量:问题出来了,token拿到了但是灰色加横线,不可用,然后其他接口也...

推荐文章

热门文章

相关标签