首页 > 其他分享 >vue3的宏到底是什么东西?

vue3的宏到底是什么东西?

时间:2024-02-19 15:57:16浏览次数:22  
标签:__ vue 浏览器 到底 东西 props vue3 title defineProps

前言

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的团队成员 三咲智子

如果我的文章对你有点帮助,欢迎关注公众号:【欧阳码农】,文章在公众号首发。你的支持就是我创作的最大动力,感谢感谢!

标签:__,vue,浏览器,到底,东西,props,vue3,title,defineProps
From: https://www.cnblogs.com/heavenYJJ/p/18021306

相关文章

  • vite+vue3+ts+ element-plus 5分钟快速搭建高端大气上档次的企业级网站前端框架
    原文地址:https://mp.weixin.qq.com/s/BANsRtNn5u-4521nFwF3FA一、安装需要的包:1、 element-plus 安装命令:npminstallelement-plus--save  2、vue-router安装命令:npminstallvue-router --save  安装完成后,需要到main.ts注册:import{createApp}from......
  • Vite+Vue3+TS创建前端页面,收费教程都没有这么详细
    原文地址:https://mp.weixin.qq.com/s/HqLgf2TCVqnndSxJw_1RTQ一、准备工作在学习之前,需要安装两个工具,一个是IDE,一个是Node.js:VsCode: https://code.visualstudio.com/DownloadNode.js: http://nodejs.cn/download/安装过程略,安装好之后,为了在vscode中能智能提示和运行,......
  • Vue3实现加入购物车抛物线效果组件
    前言在前几天的一次迭代中,我遇到了这么一个需求,模仿支付宝首页应用中心的编辑功能,支持编辑首页展示的应用,在支付宝应用首页编辑功能中,我注意到一种独特而细致的设计。无论是增加还是移除某个应用,都会引发一个精美的移动动画效果。这种贴心的设计在用户体验中起到了微妙而关键的作......
  • 从本次战疫,作为普通人可以学到的东西
    前人不忘,后事之师。从本次疫情的控制,可以学到什么?早发现,早隔离,早识别,早就诊。定位传染源,传播途径,传播方法,确定潜伏期,检测方法,确认病人症状。阻断传播途径:疑似和确诊分开。轻症和重症分开。区域间隔离。动员能力医疗物资,生产,运输,仓储,分发医院人力资源,医生,护士,护工,行政......
  • 东西
     走东店窜西铺的意思:走东家串西家,表面意思是喜欢串门,喜欢打交道的意思。东家,指的是正统。自古以来东为上、为大、为正宗,东家即为正宗的人家,东位即代表主人,比如我们常说的做东,指的是主任请客,东道主,也包含了这个意思。另外,东道主源自一个故事,古代秦国攻打郑国,郑文公答应提供后......
  • Vue3杂碎知识记录
    vue引入bootstrap当卸载App.vue里不行的时候就还可以写在main.js里导入bootstrap的时候写在main.js里,(还要添加依赖@popperjs/core)import'bootstrap/dist/css/bootstrap.css';import'bootstrap/dist/js/bootstrap';//注意js文件也要引入进来写在vue的script里面不行,要......
  • Vue3学习(16) - 左侧显示分类菜单
    写在前面和大家不太一样,我觉得今年的自己更加relax,没有亲戚要走,没有朋友相聚,也没有很好的哥们要去叙旧,更没有无知的相亲,甚至可以这么说没有那些闲得慌的邻居。也可以说是从今天开始,算是可以进入自己的小世界,做自己想做的事,看看书,学习一下。生活的精髓在于善待自己,用心感受每一......
  • python3.9 + django4.1 + vue3 ,报错,无法访问配置的路由地址,Using the URLconf defined
    python3.9+django4.1+vue3,报错,无法访问配置的路由地址,UsingtheURLconfdefinedinStudentMgrBE.urls,DjangotriedtheseURLpatterns,inthisorder:-------------------------------------------------------------------------------无法访问 地址,报错如下: Us......
  • Vite+Vue3项目如何获取环境配置,并解决前端跨域问题
    步骤根目录新建.env.development和.env.production文件package.json配置启动参数vite命令启动项目时,指定mode参数,加载vite.config.ts文件。"dev":"vite--host0.0.0.0--port8093--modedevelopment","prod":"vite--port8093--host0.0.0.0--modepr......
  • vue3 let,var,const区别
    在Vue3中,let、var和const都是用于声明变量的关键字区别:   var:在JavaScript中,var是声明变量的最常用的关键字。var声明的变量的作用域是函数级的,如果在函数内部声明的变量,其作用域将限制在函数体内部。如果在函数外部声明的变量,则其作用域将是全局的。   let:let也用于声明......