你不知道的Vue最新功能:Vue Macros

我不知道大家有没有记得Vue3之前有一个很激进的RFC$:,目的是消除使用ref时的.value。但是后来很多反对,说Vue篡改js语法含义,后来才变成了$ref,当时这个这个功能就是通过Macros来配置的。

Vue3其实有很多很先进或者是灰度测试中的功能,都会放到Vue Macros这个插件里去实现,因此我们通过这个插件提前体验未来的Vue Features。

先把官网放这里 vue-macros.dev/zh-CN/

如何配置Macros

Macros是一个插件,我们首先需要安装一下 npm i -D unplugin-vue-macros,然后我们在具体的打包器里配置一下,我目前都是用vite的,因此我们直接看vite的配置

typescript 复制代码
// vite.config.ts
import VueMacros from 'unplugin-vue-macros/vite'
import Vue from '@vitejs/plugin-vue'
// import VueJsx from '@vitejs/plugin-vue-jsx'

export default defineConfig({
  plugins: [
    VueMacros({
      plugins: {
        vue: Vue(),
        // vueJsx: VueJsx(), // 如果需要
      },
    }),
  ]
})

从这个配置方法看,它其实是在Vue插件外层包了一层,具体的源码实现不在此篇文章的讨论范畴之内,我们看一下它提供了哪些有趣的功能

Macros提供了什么

【稳定】betterDefine 支持引入类型

vue3的props一开始是不支持引入外部类型的,所以才有了这个提案。但我记得好像3.3就解决这个问题了,评论区里知道的可以给我说下

vue 复制代码
<script setup lang="ts"> 
    import type { BaseProps } from './types' 
    
    interface Props extends BaseProps { foo: string } 
    
    defineProps<Props>() 
</script>

【稳定】$defineProps 让props可以直接解构

我们都知道,正常的vue3里的props是不能解构的,解构会失去响应,因此才有了这个提案。

vue 复制代码
const {a} = $defineProps({
    a:{type:String},
    b:{type:Boolean}
})
console.log(a.value)

其实我们也可以使用toRefs来实现这个功能

vue 复制代码
const props = defineProps({
    a:{type:String},
    b:{type:Boolean}
})
const {a} = toRefs(props)
console.log(a.value)

【实验】defineProp、defineEmit 单个声明prop或emit

这个其实只是一个很小的功能点,我甚至觉得它跟上一个功能是一样的,只是实现思路不同。它主要用来声明单个prop或emit。 先看一下vue3正常的写法

vue 复制代码
const props = defineProps({
    a:{type:String},
    b:{type:Boolean}
})
console.log(props.a,props.b)

当你开启这个功能的时候,你就可以这样写.defineEmit同理,就不再赘述了

vue 复制代码
const a = defineProp('a',{type:String})
const b = defineProp('b',{type:String})
console.log(a.value,b.value)

【稳定】# Reactivity Transform 减少Ref使用的心智负担

【实验】defineRender 让Vue更像React

如果说上面两个只是小功能,小tips,那么这个defineRender就是一个颠覆性的更新了。 先看一下vue3中如何使用的渲染函数

vue 复制代码
<script>
import {h} from 'vue'
    export default defineComponent({
        name:'TestRenderer',
        setup(){
            return ()=>h('h1','renderer')
        }
    })
</script>

当我们使用defineRender之后,就可以直接渲染函数了,通过配置jsx,我们可以不需要再用数组嵌套的写法,可以直接写jsx

vue 复制代码
<script setup lang="tsx">
// 可以直接传递 JSX
defineRender(
  <div>
    <span>Hello</span>
  </div>,
)

// 或使用渲染函数
defineRender(() => {
  return (
    <div>
      <h1>Hello World</h1>
    </div>
  )
})
</script>

看看这写法,不就是妥妥的react-like

【实验】# setupComponent、setupSFC 完全拥抱JSX,简直和React一模一样

当我觉得defineRender已经是我想象力的极限的时候,vue这群大佬更加激进,反正已经react-like了,不如就变成react。 首先按照文档,我们需要配置一下vite,扩展一下Vue支持的文件后缀,新增.setup和jsx,没错就是react常用的jsx,tsx。

javascript 复制代码
export default defineConfig({ 
    plugins: [ 
    VueMacros({ 
        plugins: { 
            vue: Vue({ include: [/\.vue$/, /\.setup\.[cm]?[jt]sx?$/], 
                    // ⬆️ 需要添加 setup 模式
                    }), 
            }, 
        }), 
     ], 
 })

这两种方法使用起来基本一样,我就没分开。

tsx 复制代码
export const App = defineSetupComponent(() => {
  defineProps<{
    foo: string
  }>()

  defineEmits<{
    (evt: 'change'): void
  }>()

  defineOptions({
    name: 'App',
  })


  return (
      <div>
        <h1>Hello World</h1>
      </div>
    )
})

这不就是react的函数式写法吗,稍有不同的vue自定义了需要宏函数,方便咱们使用。

setupSFC则是更加激进,我们无需在包裹defineSetupComponent这个函数了,可以用script setup的写法,甚至连script setup都省了,我把上面那个写法改一下,你们就知道了。

tsx 复制代码
// Foo.setup.tsx
defineProps<{
  foo: string
}>()

defineEmits<{
  (evt: 'change'): void
}>()

export default () => (
  <div>
    <h1>Hello World</h1>
  </div>
)

好吧,这很react,如果哪一天Vue的知名度远远超过React,会不会有人会说这是Vue-like的写法呢?

相关推荐
真的很上进23 分钟前
如何借助 Babel+TS+ESLint 构建现代 JS 工程环境?
java·前端·javascript·css·react.js·vue·html
web1309332039829 分钟前
vue elementUI form组件动态添加el-form-item并且动态添加rules必填项校验方法
前端·vue.js·elementui
supermapsupport2 小时前
iClient3D for Cesium在Vue中快速实现场景卷帘
前端·vue.js·3d·cesium·supermap
m0_748254882 小时前
vue+elementui实现下拉表格多选+搜索+分页+回显+全选2.0
前端·vue.js·elementui
噢,我明白了4 小时前
同源策略:为什么XMLHttpRequest不能跨域请求资源?
javascript·跨域
sanguine__4 小时前
APIs-day2
javascript·css·css3
苹果醋34 小时前
Golang的文件加密工具
运维·vue.js·spring boot·nginx·课程设计
关你西红柿子4 小时前
小程序app封装公用顶部筛选区uv-drop-down
前端·javascript·vue.js·小程序·uv
济南小草根4 小时前
把一个Vue项目的页面打包后再另一个项目中使用
前端·javascript·vue.js
小木_.5 小时前
【python 逆向分析某有道翻译】分析有道翻译公开的密文内容,webpack类型,全程扣代码,最后实现接口调用翻译,仅供学习参考
javascript·python·学习·webpack·分享·逆向分析