Vue3.3 编译宏

news2024/9/21 10:35:34

image.png

Vue 3.3新增了一些语法糖和宏,包括泛型组件、defineSlots、defineEmits、defineOptions

defineProps

  • 父子组件传参
<template>
 <div>
    <Child name="xiaoman"></Child>
 </div>
</template>
 <script lang='ts' setup>
 import Child from './views/child.vue'
</script>
<style></style>

子组件使用defineProps接受值

<template>
 <div>
     {{ name }}
 </div>
</template>
 <script  lang='ts' setup>
 defineProps({
     name: String
 })
</script>
  • 使用TS字面量模式
<template>
 <div>
     {{ name }}
 </div>
</template>
 <script  lang='ts' setup>
 defineProps<{
    name:string
 }>()
</script>
  • Vue3.3 新增 defineProps 可以接受泛型
 <Child :name="['xiaoman']"></Child>
 //-------------子组件-----------------
 <template>
 <div>
     {{ name }}
 </div>
</template>
 <script generic="T"  lang='ts' setup>
 defineProps<{
    name:T[]
 }>()
</script>

defineEmits

  • 父组件
<template>
 <div>
    <Child @send="getName"></Child>
 </div>
</template>
 <script lang='ts' setup>
 import Child from './views/child.vue'
 const getName = (name: string) => {
     console.log(name)
 }
</script>
<style></style>

子组件常规方式派发Emit

<template>
 <div>
    <button @click="send">派发事件</button>
 </div>
</template>
 <script  lang='ts' setup>
const emit = defineEmits(['send'])
const send = () => {
    // 通过派发事件,将数据传递给父组件
    emit('send', '我是子组件的数据')
}
</script>

子组件TS字面量模式派发

<template>
 <div>
    <button @click="send">派发事件</button>
 </div>
</template>
 <script  lang='ts' setup>
const emit = defineEmits<{
    (event: 'send', name: string): void
}>()
const send = () => {
    // 通过派发事件,将数据传递给父组件
    emit('send', '我是子组件的数据')
}
</script>

Vue3.3 新写法更简短

<template>
 <div>
    <button @click="send">派发事件</button>
 </div>
</template>
 <script  lang='ts' setup>
const emit = defineEmits<{
    'send':[name:string]
}>()
const send = () => {
    // 通过派发事件,将数据传递给父组件
    emit('send', '我是子组件的数据')
}
</script>

defineExpose

没变化

defineExpose({
    name:"张三"
})

defineSlots

  • 父组件
<template>
    <div>
        <Child :data="list">
            <template #default="{item}">
                   <div>{{ item.name }}</div>
            </template>
        </Child>
    </div>
</template>
<script lang='ts' setup>
import Child from './views/child.vue'
const list = [
    {
        name: "张三"
    },
    {
        name: "李四"
    },
    {
        name: "王五"
    }
]
</script>
<style></style>

子组件 defineSlots只做声明不做实现 同时约束slot类型

<template>
 <div>
     <ul>
        <li v-for="(item,index) in data">
            <slot :index="index" :item="item"></slot>
        </li>
     </ul>
 </div>
</template>
 <script generic="T"  lang='ts' setup>
defineProps<{
    data: T[]
}>()
defineSlots<{
   default(props:{item:T,index:number}):void
}>()
</script>

defineOptions

  • 主要是用来定义 Options API 的选项

常用的就是定义name 在seutp 语法糖模式发现name不好定义了需要在开启一个script自定义name现在有了defineOptions就可以随意定义name了

defineOptions({
    name:"Child",
    inheritAttrs:false,
})

defineModel

由于该API处于实验性特性 可能会被删除暂时不讲

 warnOnce(
    `This project is using defineModel(), which is an experimental ` +
      `feature. It may receive breaking changes or be removed in the future, so ` +
      `use at your own risk.\n` +
      `To stay updated, follow the RFC at https://github.com/vuejs/rfcs/discussions/503.`
  )

源码解析

  • core\packages\compiler-sfc\src\script\defineSlots.ts
export function processDefineSlots(
  ctx: ScriptCompileContext,
  node: Node,
  declId?: LVal
): boolean {
  //是否调用了defineSlots
  if (!isCallOf(node, DEFINE_SLOTS)) {
    return false
  }
  //是否重复调用了defineSlots
  if (ctx.hasDefineSlotsCall) {
    ctx.error(`duplicate ${DEFINE_SLOTS}() call`, node)
  }
  //函数将 ctx 对象的 hasDefineSlotsCall 属性设置为 true,表示已经调用了 DEFINE_SLOTS 函数
  ctx.hasDefineSlotsCall = true

  //然后函数检查传递给 DEFINE_SLOTS 函数的参数个数是否为零,如果不是,则函数抛出错误,指示 DEFINE_SLOTS 函数不接受参数。
  if (node.arguments.length > 0) {
    ctx.error(`${DEFINE_SLOTS}() cannot accept arguments`, node)
  }
//接下来,如果函数接收到了一个可选的表示插槽定义的标识符的节点对象,
//则函数使用 ctx.s.overwrite 
//方法将该节点对象替换为一个表示使用插槽的帮助函数的调用
  if (declId) {
    ctx.s.overwrite(
      ctx.startOffset! + node.start!, //开始位置
      ctx.startOffset! + node.end!, //结束位置
      `${ctx.helper('useSlots')}()` //替换的内容 此时就拥有了类型检查
    )
  }

  return true
}

  • core\packages\compiler-sfc\src\script\defineOptions.ts
export function processDefineOptions(
  ctx: ScriptCompileContext,
  node: Node
): boolean {
  //是否调用了defineOptions
  if (!isCallOf(node, DEFINE_OPTIONS)) {
    return false
  }
  //是否重复调用了defineOptions
  if (ctx.hasDefineOptionsCall) {
    ctx.error(`duplicate ${DEFINE_OPTIONS}() call`, node)
  }
  //defineOptions()不能接受类型参数
  if (node.typeParameters) {
    ctx.error(`${DEFINE_OPTIONS}() cannot accept type arguments`, node)
  }
  //defineOptions()必须接受一个参数
  if (!node.arguments[0]) return true

  //函数将 ctx 对象的 hasDefineOptionsCall 属性设置为 true,表示已经调用了 DEFINE_OPTIONS 函数
  ctx.hasDefineOptionsCall = true
  //函数将 ctx 对象的 optionsRuntimeDecl 属性设置为传递给 DEFINE_OPTIONS 函数的参数
  ctx.optionsRuntimeDecl = unwrapTSNode(node.arguments[0])

  let propsOption = undefined
  let emitsOption = undefined
  let exposeOption = undefined
  let slotsOption = undefined
  //遍历 optionsRuntimeDecl 的属性,查找 props、emits、expose 和 slots 属性
  if (ctx.optionsRuntimeDecl.type === 'ObjectExpression') {
    for (const prop of ctx.optionsRuntimeDecl.properties) {
      if (
        (prop.type === 'ObjectProperty' || prop.type === 'ObjectMethod') &&
        prop.key.type === 'Identifier'
      ) {
        if (prop.key.name === 'props') propsOption = prop
        if (prop.key.name === 'emits') emitsOption = prop
        if (prop.key.name === 'expose') exposeOption = prop
        if (prop.key.name === 'slots') slotsOption = prop
      }
    }
  }
  //禁止使用defineOptions()来声明props、emits、expose和slots
  if (propsOption) {
    ctx.error(
      `${DEFINE_OPTIONS}() cannot be used to declare props. Use ${DEFINE_PROPS}() instead.`,
      propsOption
    )
  }
  if (emitsOption) {
    ctx.error(
      `${DEFINE_OPTIONS}() cannot be used to declare emits. Use ${DEFINE_EMITS}() instead.`,
      emitsOption
    )
  }
  if (exposeOption) {
    ctx.error(
      `${DEFINE_OPTIONS}() cannot be used to declare expose. Use ${DEFINE_EXPOSE}() instead.`,
      exposeOption
    )
  }
  if (slotsOption) {
    ctx.error(
      `${DEFINE_OPTIONS}() cannot be used to declare slots. Use ${DEFINE_SLOTS}() instead.`,
      slotsOption
    )
  }

  return true
}

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

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

相关文章

简要介绍 | 两阶段点云目标检测:理论与实践

注1&#xff1a;本文系“简要介绍”系列之一&#xff0c;仅从概念上对两阶段点云目标检测进行非常简要的介绍&#xff0c;不适合用于深入和详细的了解。 两阶段点云目标检测&#xff1a;理论与实践 在这篇博客中&#xff0c;我们将探索两阶段点云目标检测的理论基础和实际应用…

【朱颜不曾改,芳菲万户香。AIGC人物图片创作---InsCode Stable Diffusion 美图活动一期】

【朱颜不曾改&#xff0c;芳菲万户香。AIGC人物图片创作 ---InsCode Stable Diffusion 美图活动一期】 本文目录&#xff1a; 一、 Stable Diffusion 模型在线使用 1.1、模板运行环境配置 1.2、运行InsCode平台的Stable Diffusion模板 二、Stable Diffusion主界面功能 2.…

【5G PHY】5G控制资源集CORESET介绍

博主未授权任何人或组织机构转载博主任何原创文章&#xff0c;感谢各位对原创的支持&#xff01; 博主链接 本人就职于国际知名终端厂商&#xff0c;负责modem芯片研发。 在5G早期负责终端数据业务层、核心网相关的开发工作&#xff0c;目前牵头6G算力网络技术标准研究。 博客…

OpenCV 的安装与配置指南(Windows环境,Python语言)

OpenCV 的安装与配置指南&#xff08;Windows环境&#xff0c;Python语言&#xff09; 导语一、安装 Python 二、安装 OpenCV 库三、配置 OpenCV 环境变量四、验证 OpenCV 安装总结 导语 OpenCV 是一个功能强大的计算机视觉库&#xff0c;广泛应用于图像处理和计算机视觉领域。…

解决IDEA/WebStorm的Ctrl+Shift+F冲突失效

IDEA 的 CtrlShiftF 是全文或全项目搜索搜索快捷键&#xff0c;非常好用。 当这个快捷键偶而会失效时&#xff0c;基本可以确定是快捷键冲突了。 检查所有运行的软件的快捷键&#xff0c;若有设置为CtrlShiftF的则改掉。特别是输入法会占用较多的快捷键。 例如我这里的搜过输…

MySQL表单查询

根据题目完成下列要求 CREATE TABLE emp ( empno int(4) NOT NULL, ename varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, job varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, mgr int(4) NULL DEFAULT …

网络管理(包括网络管理的功能,管理系统及相关协议:SNMP,CMIS/CMIP)

1.OSI定义的网络管理 OSI定义的网络管理功能有以下5大类 (1)性能管理(PerformanceManagement) 在最少的网络资源和最小时延的前提下&#xff0c;网络能提供可靠、连续的通信能力。性能管理的功能有性能检测、性能分析、性能管理、性能控制。 (2)配置管理(ConfigurationManagem…

基于Arduino、BMP280、RC2202A开发的无线传感系统——测量温度和气压

核心器件 1. Arduino UNO 2. BMP280 可测量温度&#xff0c;气压(气压可换算为高度)。功耗为为微瓦级。 3. OLED 128x32 4. RC2202A 目前最低功耗的蓝牙模块&#xff08;功耗微瓦级&#xff09;&#xff0c;只支持从模式。 接线方式 代码 #include <Adafruit_SSD130…

outlook如何添加联系人群组?

如下图所示&#xff0c;新增联系人组 从通讯录选择组内用户 填写组名&#xff0c;点保存 以后在outlook写邮件时&#xff0c;就能联想使用你创建的群组了

RabbitMQ系列(27)--RabbitMQ使用Federation Exchange(联邦交换机)解决异地访问延迟问题

前言&#xff1a; (broker北京)、(broker深圳)彼此之间相距甚远&#xff0c;网络延迟是一个不得不面对的问题。有一个在北京的业务(Client北京&#xff09;需要连接(broker北京),向其中的交换器exchangeA发送消息&#xff0c;此时的网络延迟很小,(Client北京)可以迅速将消息发…

macOS访达当前目录打开终端

在windows 11中&#xff0c;可以在【此电脑】中任意文件夹中鼠标右键&#xff0c;可能直接在当前目录打开【终端】。用久也感觉还是很方便的。 与是在macOS中&#xff0c;我也想得到类似的功能。如何实现记录下来。 实战过程 我的实战环境是&#xff1a; 操作系统&#xff1a…

【数据结构常见七大排序(一)】—插入排序篇【直接插入排序】And【希尔排序】

目录 1.排序的概念及其运用 1.1排序的概念 1.2排序运用 1.3常见的七大排序 2.直接插入排序 2.1基本思想 2.2直接插入排序 2.3动图助解 2.4直接插入排序源码 2.5直接插入排序的特性总结 3.希尔排序( 缩小增量排序 ) 3.1希尔排序概念及思想 3.2希尔排序图解 3.3希尔…

用颜色表示数据的第三个维度

横纵坐标显示时间和空间后&#xff0c;第三个数据的特征有时就不好表示了&#xff0c;3d图有的时候看起来更复杂。对于某些情况&#xff0c;用颜色来表示更加简洁。 这里展示的效果图有点像烟花&#xff0c;所以选了这张&#xff0c;但是换其他的cmap才能使得数据展示更加直观 …

举例解释Lingo的条件执行@if语句

可变成本问题 某公司生产A、B、C共3种产品&#xff0c;售价分别是12元、7元和6元。生产1件这些产品的技术服务、直接劳动、材料的消耗以及这些资源的限量如表所示。 产品\项目 技术服务(h) 直接劳动(h) 材料(kg) 售价(&#xffe5;/件&#xff09; A 1 10 3 12 B 2…

Linux的

&#xff08;该图由AI绘制 关注我 学习AI画图&#xff09; 目录 网络配置 1、ifconfig查看网络信息 2、与网卡相关的配置文件 3、查询计算机的网络状态 4、systemctl启动/重启/停止网络 Linux远程连接与文件传输 1、为什么需要远程连接 2、SSH协议 3、sshd服务 4、…

SpringBoot——设置随机值测试

在测试中加入随机值 之前我们在测试的时候都是写死的数据&#xff0c;但是有时候我们的数据并不一定是已知的数据&#xff0c;有可能你不知道用户要输入什么数据&#xff0c;这时候我们可以用随机值的方式进行代码的测试。 设置随机值 设置随机值的方式非常简单&#xff0c;…

6-开发模型(5个)

目录 1.瀑布模型&#xff08;Waterfall Model&#xff09; 2.螺旋模型&#xff08;Spiral Model&#xff09; 3.增量模型&#xff08;Incremental Model&#xff09; 4.迭代模型&#xff08;Iterative Model&#xff09; PS&#xff1a;增量模型和迭代模型的区别 5.敏捷模…

暑假第五天打卡

Java //1、练习题&#xff1a;判断如下代码是否编译通过&#xff0c;如果能&#xff0c;结果是多少&#xff1f; short s1 120; short s2 8; short s3 s1 s2; //编译不通过&#xff0c;因为s1s2自动提示为int类型 //3、练习题&#xff1a;判断如下代码是否编译通过&am…

雅思考试口语怎么备考才能拿到7分

很多学生在雅思考试里拿到总分7分的好成绩&#xff0c;雅思的口语要怎么准备才能拿到这样的好成绩&#xff1f;其实雅思口语7分的难度不高&#xff0c;下面就来看看雅思口语应该如何备考&#xff1f; 一、雅思口语考试怎么考7分 1、“流利度”如何拿7分 很多雅思口语提升攻略…

【算法】算法笔记(C++)

一、数组 求数组大小 nums.size()//防止报错 数组中的按大小排序 sort(nums.begin(), nums.end()); 获取最大值/最小值 int nums[8] {1,2,3,8,0,33,11,9}; int max_num *max_element(nums, nums 8); int min_num *min_element(nums, nums 8); 将数组a中的数值置为0…