vue3【详解】单文件组件 SFC(含SFC的优点、缺点、使用场景、原理、使用预处理器、<script setup>语法详解、资源拆分)

SFC 概述

将一个组件的逻辑 (JavaScript),模板 (HTML) 和样式 (CSS) 封装在同一个.vue 文件里,即单文件组件( Single-File Components,缩写为 SFC)。

<script setup>
import { ref } from 'vue'
const count = ref(0)
</script><template><button @click="count++">Count is: {{ count }}</button>
</template><style scoped>
button {font-weight: bold;
}
</style>

每一个 *.vue 文件都由三种顶层语言块构成:<template><script><style>

  • 最多可以包含一个顶层 <template> 块,其包裹的内容将会被提取、传递给 @vue/compiler-dom,预编译为 JavaScript 渲染函数,并附在导出的组件上作为其 render 选项。

  • 最多可以包含一个 <script> 块。(使用 <script setup> 的情况除外)

  • 最多可以包含一个 <script setup>。(不包括一般的 <script>) , 这个脚本块将被预处理为组件的 setup() 函数,这意味着它将为每一个组件实例都执行。<script setup> 中的顶层绑定都将自动暴露给模板。

  • 可以包含多个 <style> 标签,可以使用 scoped 或 module attribute 来帮助封装当前组件的样式。使用了不同封装模式的多个 <style> 标签可以被混合入同一个组件。

  • 语言块内的注释,使用各自语言对应的注释语法

    // js 的注释 
    
    <!-- html 的注释 -->
    
    /* css 的注释 */
    
  • 语言块外的注释,使用 HTML 的注释语法

     <!-- 注释内容 -->
    

SFC 的优点

  • 使用熟悉的 HTML、CSS 和 JavaScript 语法编写模块化的组件
  • 让本来就强相关的关注点自然内聚
  • 预编译模板,避免运行时的编译开销
  • 组件作用域的 CSS
  • 在使用组合式 API 时语法更简单
  • 通过交叉分析模板和逻辑代码能进行更多编译时优化
  • 更好的 IDE 支持,提供自动补全和对模板中表达式的类型检查
  • 开箱即用的模块热更新 (HMR) 支持

SFC 的缺点

必须使用构建工具

SFC 的使用场景

  • 单页面应用 (SPA)
  • 静态站点生成 (SSG)
  • 任何值得引入构建步骤以获得更好的开发体验 (DX) 的项目

SFC 的原理

SFC 会在打包构建过程中,通过@vue/compiler-sfc 编译为标准的 JavaScript 和 CSS。

  • 开发阶段:<style> 标签会注入成原生的 <style> 标签以支持热更新
  • 生产环境: <style> 标签会被抽取、合并成单独的 CSS 文件

使用预处理器

需在语言块标签的 lang 属性中声明预处理器

script 使用 TypeScript

<script lang="ts">// ts 代码
</script>

template 使用 Pug

<template lang="pug">
p {{ msg }}
</template>

style 使用 Sass

<style lang="scss">$primary-color: #333;body {color: $primary-color;}
</style>

<script setup>

SFC 中使用组合式 API 默认会推荐使用<script setup> 语法糖,相比于普通的 <script> ,它具有更多优势:

  • 更少的样板内容,更简洁的代码。
  • 能够使用纯 TypeScript 声明 props 和自定义事件。
  • 更好的运行时性能 (其模板会被编译成同一作用域内的渲染函数,避免了渲染上下文代理对象)。
  • 更好的 IDE 类型推导性能 (减少了语言服务器从代码中抽取类型的工作)。

运行机制

  • 普通的 <script> 只在组件被首次引入的时候执行一次
  • <script setup>中的代码会被编译成组件 setup() 函数的内容,在每次组件实例被创建的时候执行

顶层声明在模板中可直接使用

<script setup>
// 导入的函数
import { capitalize } from './helpers'
// 导入的组件(强烈建议使用 PascalCase 格式)
import MyComponent from './MyComponent.vue'// 变量
const msg = 'Hello!'// 函数
function log() {console.log(msg)
}
</script><template><button @click="log">{{ msg }}</button><div>{{ capitalize('hello') }}</div><MyComponent />
</template>

递归组件

名为 FooBar.vue 的组件可以在其模板中用 <FooBar/> 引用它自己。

这种方式相比于导入的组件优先级更低。

如果有具名的导入和组件自身推导的名字冲突了,可以为导入的组件添加别名

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

从单文件中导入多个组件

将组件嵌套在对象属性中,使用带 . 的组件标签在模板中使用。

<script setup>
import * as Form from './form-components'
</script><template><Form.Input><Form.Label>label</Form.Label></Form.Input>
</template>

使用自定义指令

自定义指令必须遵循 vNameOfDirective 命名规范(自定义指令名的首字母必须是 v ,后续跟首字母大写的自定义指令名称 )

<script setup>
const vMyDirective = {beforeMount: (el) => {// 在元素上做些操作}
}
</script>
<template><h1 v-my-directive>This is a Heading</h1>
</template>

导入的自定义指令,可以通过重命名来使其符合命名规范:

<script setup>
import { myDirective as vMyDirective } from './MyDirective.js'
</script>

defineProps

无需导入,可直接使用,参数与 props 选项相同

<script setup>
const props = defineProps({foo: String,bar?: Number
})
</script>

TS 中的写法

const props = defineProps<{foo: string,bar?: number
}>()

添加默认值需使用 withDefaults

export interface Props {msg?: stringlabels?: string[]
}const props = withDefaults(defineProps<Props>(), {msg: 'hello',labels: () => ['one', 'two']
})

defineEmits

无需导入,可直接使用,参数与 emits 选项相同

const emit = defineEmits(['change', 'delete'])

TS 中的写法

const emit = defineEmits<{(e: 'change', id: number): void(e: 'update', value: string): void
}>()// 3.3+:另一种更简洁的语法
const emit = defineEmits<{change: [id: number] // 具名元组语法update: [value: string]
}>()

defineModel

vue3.4 新增
无需导入,可直接使用,用来声明一个双向绑定 prop,详细用法见
https://cn.vuejs.org/guide/components/v-model.html

解构 defineModel() 的返回值可以获取 v-model 指令使用的修饰符

const [modelValue, modelModifiers] = defineModel()// 对应 v-model.trim
if (modelModifiers.trim) {// ...
}

通过 get 和 set 转换器选项可以在同步回父组件时对其值进行转换

const [modelValue, modelModifiers] = defineModel({// get() 省略了,因为这里不需要它set(value) {// 如果使用了 .trim 修饰符,则返回裁剪过后的值if (modelModifiers.trim) {return value.trim()}// 否则,原样返回return value}
})

TS 中

const modelValue = defineModel<string>()
// ^? Ref<string | undefined>// 用带有选项的默认 model,设置 required 去掉了可能的 undefined 值
const modelValue = defineModel<string>({ required: true })
// ^? Ref<string>const [modelValue, modifiers] = defineModel<string, "trim" | "uppercase">()
// ^? Record<'trim' | 'uppercase', true | undefined>

defineExpose

使用 <script setup> 的组件默认是关闭的(通过模板引用或者 $parent 链无法获取到组件中的绑定,如声明的变量,导入的函数等)

需通过 defineExpose 来显式指定对外暴露的属性:

<script setup>
import { ref } from 'vue'const a = 1
const b = ref(2)defineExpose({a,b
})
</script>

此时,父组件通过模板引用的方式获取到的当前组件的实例为 { a: number, b: number }

defineOptions

Vue 3.3 新增
用于声明组件选项,避免使用单独的 <script>

<script setup>
defineOptions({inheritAttrs: false,customOptions: {/* ... */}
})
</script>

选项中无法访问 <script setup> 中不是字面常数的局部变量。

defineSlots

Vue 3.3 新增
用于为 IDE 提供插槽名称和 props 类型检查的类型提示。

<script setup lang="ts">
const slots = defineSlots<{default(props: { msg: string }): any
}>()
</script>

defineSlots() 只接受类型参数,没有运行时参数。类型参数应该是一个类型字面量,其中属性键是插槽名称,值类型是插槽函数。函数的第一个参数是插槽期望接收的 props,其类型将用于模板中的插槽 props。返回类型目前被忽略,可以是 any,但我们将来可能会利用它来检查插槽内容。

它还返回 slots 对象,该对象等同于在 setup 上下文中暴露或由 useSlots() 返回的 slots 对象。

与普通的 <script> 一起使用

仅在有下述需求时使用:

  • 声明模块的具名导出 (named exports)。
  • 运行只需要在模块作用域执行一次的副作用,或是创建单例对象。
<script>
// 普通 <script>,在模块作用域下执行 (仅一次)
runSideEffectOnce()
</script><script setup>
// 在 setup() 作用域中执行 (对每个实例皆如此)
</script>

在顶层可以直接使用 await

因为代码会被编译成 async setup()

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

获取组件实例

通过 getCurrentInstance 获取

资源拆分 src

如果不喜欢单文件组件这样的形式,可以按下方代码拆分单独的 HTML、JavaScript 和 CSS 文件

<template src="./template.html"></template>
<style src="./style.css"></style>
<script src="./script.js"></script>

由于模块执行语义的差异,<script setup> 中的代码依赖单文件组件的上下文。当将其移动到外部的 .js 或者 .ts 文件中的时候,对于开发者和工具来说都会感到混乱。因此,<script setup> 内的 JS 代码无法使用 src 拆分。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Java SpringAOP简介

简介 官方介绍&#xff1a; SpringAOP的全称是&#xff08;Aspect Oriented Programming&#xff09;中文翻译过来是面向切面编程&#xff0c;AOP是OOP的延续&#xff0c;是软件开发中的一个热点&#xff0c;也是Spring框架中的一个重要内容&#xff0c;是函数式编程的一种衍生…

SpringBatch文件读写ItemWriter,ItemReader使用详解

SpringBatch文件读写ItemWriter&#xff0c;ItemReader使用详解 1. ItemReaders 和 ItemWriters1.1. ItemReader1.2. ItemWriter1.3. ItemProcessor 2.FlatFileItemReader 和 FlatFileItemWriter2.1.平面文件2.1.1. FieldSet 2.2. FlatFileItemReader2.3. FlatFileItemWriter 3…

opencv—常用函数学习_“干货“_4

目录 十二、图像平滑滤波 均值滤波 (blur) 方框滤波 (boxFilter) 中值滤波 (medianBlur) 高斯滤波 (GaussianBlur) 双边滤波 (bilateralFilter) 自定义滤波器 (filter2D) 边缘保留滤波 (edgePreservingFilter) 快速非局部均值去噪 (fastNlMeansDenoising) 彩色图像的快…

Canvas API

Canvas API中文文档: canvas API中文网 - Canvas API中文文档首页地图 Web 开发技术: Canvas API - Web API | MDN (mozilla.org) HTML5 Canvas: The HTML5 Canvas Handbook (bucephalus.org)

前端内容之常用置标

最近由于换了项目组&#xff0c;目前负责需求全部是前端任务&#xff0c;为了方便后续查看&#xff0c;在此记录下&#xff01; 拓尔思常用置标 获取指定栏目的指定字段(数据库字段)的栏目信息 获取一级栏目的栏目名称 autolink为true,代表产生链接;false为不产生链接。 &l…

AI 绘画|Midjourney设计Logo提示词

你是否已经看过许多别人分享的 MJ 咒语&#xff0c;却仍无法按照自己的想法画图&#xff1f;通过学习 MJ 的提示词逻辑后&#xff0c;你将能够更好地理解并创作自己的“咒语”。本文将详细拆解使用 MJ 设计 Logo 的逻辑&#xff0c;让你在阅读后即可轻松上手&#xff0c;制作出…

R语言学习笔记8-并行计算

R语言学习笔记8-并行计算 简要说明使用parallel包使用foreach和doParallel包使用future包 简要说明 在R语言中&#xff0c;通过并行计算可以显著提升处理大数据集或执行耗时任务的效率。R提供了多种并行计算的方法&#xff0c;包括使用基础的parallel包和更高级的foreach和fut…

打包一个自己的Vivado IP核

写在前面 模块复用是逻辑设计人员必须掌握的一个基本功&#xff0c;通过将成熟模块打包成IP核&#xff0c;可实现重复利用&#xff0c;避免重复造轮子&#xff0c;大幅提高我们的开发效率。 接下来将之前设计的串口接收模块和串口发送模块打包成IP核&#xff0c;再分别调用…

知识加油站

我的&#x1f351;宝店【码猿小铺】持续进行&#xff0c;其中有Linux/shell视频&#xff08;包含项目实操&#xff09;、新版ShardingJDBC分库分表视频&#xff08;包含项目实操&#xff09;、初中高级面试专栏、React全套视频&#xff08;包含项目实操&#xff09;、新版javes…

【深度学习】FaceChain-SuDe,免训练,AI换脸

https://arxiv.org/abs/2403.06775 FaceChain-SuDe: Building Derived Class to Inherit Category Attributes for One-shot Subject-Driven Generation 摘要 最近&#xff0c;基于主体驱动的生成技术由于其个性化文本到图像生成的能力&#xff0c;受到了广泛关注。典型的研…

从MySQL迁移到PostgreSQL的完整指南

1.引言 在现代数据库管理中&#xff0c;选择合适的数据库系统对业务的成功至关重要。随着企业数据量的增长和对性能要求的提高&#xff0c;许多公司开始考虑从MySQL迁移到PostgreSQL。这一迁移的主要原因包括以下几个方面&#xff1a; 1.1 性能和扩展性 PostgreSQL以其高性能…

TCP/IP、UDP、HTTP 协议介绍比较和总结

TCP/IP、UDP、HTTP是网络通信中的三种重要协议,各自具有不同的特点和应用场景。以下是对这三种协议的详细介绍、比较和总结。 TCP/IP协议 传输控制协议/互联网协议(TCP/IP, Transmission Control Protocol/Internet Protocol) 特点: 可靠性:TCP提供可靠的通信,通过握手…

深度学习入门——神经网络

前言 神经网络可以帮助自动化设定权重 具体地讲&#xff0c;神经网络的一个重要性质是它可以自动地从数据中学习到合适的权重参数 从感知机到神经网络 神经网络的例子 中间层aka隐藏层 复习感知机 偏置b 并没有被画出来。如果要明确地表示出b&#xff0c;可以像图3-3那样做…

搜维尔科技:使用远程TCP和刀具路径遥操作点胶

使用远程TCP和刀具路径遥操作点胶 搜维尔科技&#xff1a;使用远程TCP和刀具路径遥操作点胶

Large Language Model系列之一:语言模型与表征学习(Language Models and Representation Learning)

语言模型与表征学习&#xff08;Language Models and Representation Learning&#xff09; 1 语言模型 N-Gram模型 from collections import defaultdictsentences [The swift fox jumps over the lazy dog.,The swift river flows under the ancient bridge.,The swift br…

华为1000人校园实验记录

在这里插入代码片1000人校园区网设计 1、配置Eth-trunk实现链路冗余 vlan 900 管理WLAN #接入SW8 操作&#xff1a;sys undo in en sysname JR-SW8 int Eth-Trunk 1 mode lacp-static trunkport g0/0/1 0/0/2 port link-type trunk port trunk allow-pass vlan 200 900 qu vla…

Linux C++ 056-设计模式之迭代器模式

Linux C 056-设计模式之迭代器模式 本节关键字&#xff1a;Linux、C、设计模式、迭代器模式 相关库函数&#xff1a; 概念 迭代器模式&#xff08;Iterator Pattern&#xff09;是一种常用的设计模式。迭代器模式提供一种方法顺序访问一个聚合对象中的各个元素&#xff0c;而…

模拟器小程序/APP抓包(Reqable+MUMU模拟器)

一、使用adb连接上MUMU模拟器 打开多开器点击ADB图标 连接模拟器端口&#xff1a; adb connect 127.0.0.1:16384列出已连接的设备&#xff1a; adb devices正常会显示MuMu的设备已连接 二、下载Reqable 1.下载链接&#xff1a;客户端下载 | Reqable 2.文档链接&#xff1a;…

Bigdata-Docker构建大数据学习开发环境

Bigdata-Docker构建大数据学习开发环境 介绍 1、镜像环境 系统&#xff1a;centos 7Java &#xff1a;java7Zookeeper: 3.4.6Hadoop: 2.7.1mysql: 5.6.29Hive: 1.2.1Spark: 1.6.2Hbase: 1.1.2 2、镜像介绍 tonywell/centos-java&#xff1a;openssh、java7&#xff0c;基础…

示例:在WPF ListBox中,ScrollViewer.CanContentScroll=“False“破坏虚拟化如何解决

一、目的&#xff1a;分享一个解决ListBox设置了ScrollViewer.CanContentScroll"False"破坏虚拟坏的解决方法 ScrollViewer.CanContentScroll 是 WPF 中 ScrollViewer 控件的一个属性&#xff0c;它决定了滚动内容时是按逻辑单位&#xff08;如项&#xff09;还是按物…