vue3的宏到底是什么东西?

前言

vue3开始vue引入了宏,比如definePropsdefineEmits等。我们每天写vue代码时都会使用到这些宏,但是你有没有思考过vue中的宏到底是什么?为什么这些宏不需要手动从vueimport?为什么只能在setup顶层中使用这些宏?

vue 文件如何渲染到浏览器上

要回答上面的问题,我们先来了解一下从一个vue文件到渲染到浏览器这一过程经历了什么?

我们的vue代码一般都是写在后缀名为vue的文件上,显然浏览器是不认识vue文件的,浏览器只认识html、css、jss等文件。所以第一步就是通过webpack或者vite将一个vue文件编译为一个包含render函数的js文件。然后执行render函数生成虚拟DOM,再调用浏览器的DOM API根据虚拟DOM生成真实DOM挂载到浏览器上。

 

 

vue3的宏是什么?

我们先来看看vue官方的解释:

 

宏是一种特殊的代码,由编译器处理并转换为其他东西。它们实际上是一种更巧妙的字符串替换形式。

宏是在哪个阶段运行?

通过前面我们知道了vue 文件渲染到浏览器上主要经历了两个阶段。

第一阶段是编译时,也就是从一个vue文件经过webpack或者vite编译变成包含render函数的js文件。此时的运行环境是nodejs环境,所以这个阶段可以调用nodejs相关的api,但是没有在浏览器环境内执行,所以不能调用浏览器的API

第二阶段是运行时,此时浏览器会执行js文件中的render函数,然后依次生成虚拟DOM和真实DOM。此时的运行环境是浏览器环境内,所以可以调用浏览器的API,但是在这一阶段中是不能调用nodejs相关的api

而宏就是作用于编译时,也就是从vue文件编译为js文件这一过程。

举个defineProps的例子:在编译时defineProps宏就会被转换为定义props相关的代码,当在浏览器运行时自然也就没有了defineProps宏相关的代码了。所以才说宏是在编译时执行的代码,而不是运行时执行的代码。

一个defineProps宏的例子

我们来看一个实际的例子,下面这个是我们的源代码:

<template>
  <div>content is {{ content }}</div>
  <div>title is {{ title }}</div>
</template>

<script setup lang="ts">
import {ref} from "vue"
const props = defineProps({
  content: String,
});
const title = ref("title")
</script>

 在这个例子中我们使用defineProps宏定义了一个类型为String,属性名为contentprops,并且在template中渲染content的内容。

我们接下来再看看编译成js文件后的代码,代码我已经进行过简化:

import { defineComponent as _defineComponent } from "vue";
import { ref } from "vue";

const __sfc__ = _defineComponent({
  props: {
    content: String,
  },
  setup(__props) {
    const props = __props;
    const title = ref("title");
    const __returned__ = { props, title };
    return __returned__;
  },
});

import {
  toDisplayString as _toDisplayString,
  createElementVNode as _createElementVNode,
  Fragment as _Fragment,
  openBlock as _openBlock,
  createElementBlock as _createElementBlock,
} from "vue";

function render(_ctx, _cache, $props, $setup) {
  return (
    _openBlock(),
    _createElementBlock(
      _Fragment,
      null,
      [
        _createElementVNode(
          "div",
          null,
          "content is " + _toDisplayString($props.content),
          1 /* TEXT */
        ),
        _createElementVNode(
          "div",
          null,
          "title is " + _toDisplayString($setup.title),
          1 /* TEXT */
        ),
      ],
      64 /* STABLE_FRAGMENT */
    )
  );
}
__sfc__.render = render;
export default __sfc__;

我们可以看到编译后的js文件主要由两部分组成,第一部分为执行defineComponent函数生成一个 __sfc__ 对象,第二部分为一个render函数。render函数不是我们这篇文章要讲的,我们主要来看看这个__sfc__对象。

看到defineComponent是不是觉得很眼熟,没错这个就是vue提供的API中的 definecomponent函数。这个函数在运行时没有任何操作,仅用于提供类型推导。这个函数接收的第一个参数就是组件选项对象,返回值就是该组件本身。所以这个__sfc__对象就是我们的vue文件中的script代码经过编译后生成的对象,后面再通过__sfc__.render = renderrender函数赋值到组件对象的render方法上面。

我们这里的组件选项对象经过编译后只有两个了,分别是props属性和setup方法。明显可以发现我们原本在setup里面使用的defineProps宏相关的代码不在了,并且多了一个props属性。没错这个props属性就是我们的defineProps宏生成的。

 

我们再来看一个不在setup顶层调用defineProps的例子: 

<script setup lang="ts">
import {ref} from "vue"
const title = ref("title")

if (title.value) {
  const props = defineProps({
    content: String,
  });
}
</script>

运行这个例子会报错:defineProps is not defined

我们来看看编译后的js代码:

import { defineComponent as _defineComponent } from "vue";
import { ref } from "vue";

const __sfc__ = _defineComponent({
  setup(__props) {
    const title = ref("title");
    if (title.value) {
      const props = defineProps({
        content: String,
      });
    }
    const __returned__ = { title };
    return __returned__;
  },
});

明显可以看到由于我们没有在setup的顶层调用defineProps宏,在编译时就不会将defineProps宏替换为定义props相关的代码,而是原封不动的输出回来。在运行时执行到这行代码后,由于我们没有任何地方定义了defineProps函数,所以就会报错defineProps is not defined

总结

现在我们能够回答前面提的三个问题了。

  • vue中的宏到底是什么?

    vue3的宏是一种特殊的代码,在编译时会将这些特殊的代码转换为浏览器能够直接运行的指定代码,根据宏的功能不同,转换后的代码也不同。

  • 为什么这些宏不需要手动从vueimport

    因为在编译时已经将这些宏替换为指定的浏览器能够直接运行的代码,在运行时已经不存在这些宏相关的代码,自然不需要从vueimport

  • 为什么只能在setup顶层中使用这些宏?

    因为在编译时只会去处理setup顶层的宏,其他地方的宏会原封不动的输出回来。在运行时由于我们没有在任何地方定义这些宏,当代码执行到宏的时候当然就会报错。

如果想要在vue中使用更多的宏,可以使用 vue macros。这个库是用于在vue中探索更多的宏和语法糖,作者是vue的团队成员 三咲智子 。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

无重复字符的最长子串习题分析

习题&#xff1a;&#xff08;leetcode 3 &#xff09; 给定一个字符串s&#xff0c;请你找出其中不含有重复字符的最长子串的长度。 分析&#xff1a; 对于寻找子串、数组中某部分等&#xff0c;我们可以使用滑动窗口和双指针思想来求解。 滑动窗口通常用于解决需要连续子…

Linux服务器的Tomcat9中部署War包

文章目录 Linux服务器的Tomcat9中部署War包一、引言二、部署Tomcat91、安装Tomcat91.1、下载Tomcat91.2、解压安装1.3、启动Tomcat9 2、配置环境变量&#xff08;可选&#xff09; 三、部署War包1、准备War包2、部署War包3、配置Context&#xff08;可选&#xff09; 四、启动和…

如果接口返回值图片有很长一串码,需要添加前缀

需要在前面添加前缀&#xff1a;data:image/jpeg;base64,然后将值赋值给<img :src"originalImage" /> this.tableLists.map((item)>{item.originalImage "data:image/jpeg;base64,"item.originalImage})以上方法会导致出现一个小bug&#xff0c;…

2024年11月21日Github流行趋势

项目名称&#xff1a;twenty 项目维护者&#xff1a;charlesBochet, lucasbordeau, Weiko, FelixMalfait, bosiraphael项目介绍&#xff1a;正在构建一个由社区支持的现代化Salesforce替代品。项目star数&#xff1a;21,798项目fork数&#xff1a;2,347 项目名称&#xff1a;p…

Excel——宏教程(精简版)

一、宏的简介 1、什么是宏&#xff1f; Excel宏是一种自动化工具&#xff0c;它允许用户录制一系列操作并将其转换为VBA(Visual Basic for Applications)代码。这样&#xff0c;用户可以在需要时执行这些操作&#xff0c;以自动化Excel任务。 2、宏的优点 我们可以利用宏来…

【eNSP】OSPF、RIP与静态路由互通实验(四)

OSPF、RIP与静态路由互通实验 实验目的实验要求实验步骤步骤 1&#xff1a;配置R1、R2、R3、R4、R5、R6、R7的端口ip步骤 2&#xff1a;配置R1、R2、R3的OSPF动态路由协议步骤 3&#xff1a;配置R3、R4、R5的RIP动态路由协议步骤 4&#xff1a;配置R3作为边界路由器&#xff0c…

Vision-Language Models for Vision Tasks: A Survey 论文解读

摘要 大多数视觉识别研究在深度神经网络&#xff08;DNN&#xff09;训练中严重依赖于人工标注的数据&#xff0c;且通常为每个单一的视觉识别任务训练一个DNN&#xff0c;导致这种视觉识别范式既繁琐又耗时。为解决这两个挑战&#xff0c;近年来对视觉语言模型&#xff08;VL…

Stable Diffusion核心网络结构——U-Net

​ &#x1f33a;系列文章推荐&#x1f33a; 扩散模型系列文章正在持续的更新&#xff0c;更新节奏如下&#xff0c;先更新SD模型讲解&#xff0c;再更新相关的微调方法文章&#xff0c;敬请期待&#xff01;&#xff01;&#xff01;&#xff08;本文及其之前的文章均已更新&a…

C#桌面应用制作计算器进阶版01

基于C#桌面应用制作计算器做出了少量改动&#xff0c;其主要改动为新增加了一个label控件&#xff0c;使其每一步运算结果由label2展示出来&#xff0c;而当点击“”时&#xff0c;最终运算结果将由label1展示出来&#xff0c;此时label清空。 修改后运行效果 修改后全篇代码 …

python: generator model using sql server 2019

設計或生成好數據庫&#xff0c;可以生成自己設計好的框架項目 # encoding: utf-8 # 版权所有 &#xff1a;2024 ©涂聚文有限公司 # 许可信息查看 &#xff1a;言語成了邀功盡責的功臣&#xff0c;還需要行爲每日來值班嗎 # 描述&#xff1a; : 生成实体 # Author …

【Nginx从入门到精通】04-安装部署-使用XShell给虚拟机配置静态ip

文章目录 总结1、XShell &#xff1a;方便管理多台机器2、配置ip文件&#xff1a;区分大小写 一、查看上网模式二、Centos 7 设置静态ipStage 1 &#xff1a;登录root账号Stage 2 &#xff1a;设置静态ip : 修改配置文件 <font colororange>ifcfg-ens33Stage 2-1&#xf…

【深度学习】利用Java DL4J构建金融欺诈检测系统

&#x1f9d1; 博主简介&#xff1a;CSDN博客专家&#xff0c;历代文学网&#xff08;PC端可以访问&#xff1a;https://literature.sinhy.com/#/literature?__c1000&#xff0c;移动端可微信小程序搜索“历代文学”&#xff09;总架构师&#xff0c;15年工作经验&#xff0c;…

当你项目服务器磁盘报警

当你们公司运维收到这样的邮件&#xff0c;大概率日志文件过大引起的 在Linux下如何不停止服务,清空nohup.out文件呢&#xff1f; nohup.out会一直一直自己增长下去&#xff0c;如果你的服务器硬盘不给力的话&#xff0c;很容易把应用也挂掉&#xff08;硬盘没空间 &#xff0…

面向未来的智能视觉参考设计与汽车架构,思尔芯提供基于Arm技术的创新方案

引言&#xff1a; 随着科技的飞速发展&#xff0c;智能视觉IoT已成为科技领域的热门话题&#xff0c;为智能家居、智慧城市等领域带来新机遇。然而&#xff0c;物联网市场的碎片化特性对智能视觉芯片设计构成挑战。同时&#xff0c;汽车行业正经历技术驱动的变革&#xff0c;软…

C++ 20 中 vector list stack queue 分别从功能 效率等全方面分析其差异

C++ 20 中 vector list stack queue 分别从功能 效率等全方面分析其差异 在 C++20 中,std::vector、std::list、std::stack 和 std::queue 是常用的容器或容器适配器。以下从功能、效率、使用场景等方面对它们进行详细对比。 功能对比 2.效率对比 存储和访问 扩容效率std::…

51单片机之串口通讯

1.串口简介 串口&#xff0c;全称串行通信接口或串行通讯接口&#xff08;通常指COM接口&#xff09;&#xff0c;是一种常用于电子设备间通讯的全双工扩展接口。 串口通讯的技术基础&#xff0c;指一位一位地按顺序传送数据。其特点是线路简单&#xff0c;只需一对传输线&…

UE5 DownloadImage加载jpg失败的解决方法

DownloadImage加载jpg失败的解决方法 现象解决方案具体方法 现象 用UE自带的 DownloadImage 无法下载成功&#xff0c;从 failure 引脚出来。 接入一个由监控器自动保存起的图像&#xff0c;有些可以正常加载成功&#xff0c;有些无法加载成功。 经调查问题出现在&#xff0c;…

Springboot 整合 Java DL4J 搭建智能问答系统

&#x1f9d1; 博主简介&#xff1a;CSDN博客专家&#xff0c;历代文学网&#xff08;PC端可以访问&#xff1a;https://literature.sinhy.com/#/literature?__c1000&#xff0c;移动端可微信小程序搜索“历代文学”&#xff09;总架构师&#xff0c;15年工作经验&#xff0c;…

相较于发达国家约70%的普及率,中国【台式洗碗机】渗透率仅在2%-3%之间,潜在市场增量可观

内容摘要 据 HengCe 最新调研&#xff0c;2023年中国台式洗碗机市场销售收入达到了 万元&#xff0c;预计2030年可以达到 万元&#xff0c;2024-2030期间年复合增长率(CAGR)为 %。本研究项目旨在梳理台式洗碗机领域产品系列&#xff0c;洞悉行业特点、市场存量空间及增量空间&…

自动语音识别(ASR)与文本转语音(TTS)技术的应用与发展

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…