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

本文主要讲解关于你不知道的Vue最新功能:Vue Macros相关内容,让我们来一起学习下吧!

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

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

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

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

如何配置Macros

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

// 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就解决这个问题了,评论区里知道的可以给我说下

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

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

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

const {a} = $defineProps({
    a:{type:String},
    b:{type:Boolean}
})
console.log(a.value)

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

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

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

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

const props = defineProps({
    a:{type:String},
    b:{type:Boolean}
})
console.log(props.a,props.b)

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

const a = defineProp('a',{type:String})
const b = defineProp('b',{type:String})
console.log(a.value,b.value)

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

在vue3出来之后,Ref一直被人诟病,说是.value很反直觉,但我觉得还好,这是为了响应式的一些牺牲吧,但是尤大显然不喜欢这些诟病,并致力于消除.value

官方介绍地址

一开始提出了使用冷门的label语法,也就是$:,后来被攻击说更改了js语法本意,于是放弃了。然后就便提出了本提案Reactivity Transform,大概使用如下

<script setup>
let count = $ref(0)

console.log(count)

function increment() {
  count++
}
</script>

<template>
  <button @click="increment">{{ count }}</button>
</template>

其中$ref就是一个编译器宏,告诉编译器这是一个ref变量,在后续使用中,你就可以不用写.value了,后续会自动给你加上.value
每一个Ref API 都对应着一个$XX

  • ref-> $ref
  • computed -> $computed
  • shallowRef-> $shallowRef
  • customRef -> $customRef
  • toRef -> $toRef

同时还有一个$(),用来解构CompositionAPI

import { useMouse } from '@vueuse/core'

const { x, y } = $(useMouse())

console.log(x, y)

这样就可以覆盖所有的Ref API,让你在写代码的时候不用再担心.value的问题。具体大家可以看官网,介绍的比我详细多了。

如何配置开启我多说两句,这里稍微有点差异

vue3.3以下如何启用

// vite.config.js
export default {
  plugins: [
    vue({
      reactivityTransform: true
    })
  ]
}

vue3.4及更高版本如何启用

3.4需要你安装一个包@vue-macros/reactivity-transform,然后按照插件配置进去。

import { defineConfig } from 'vite';
import Vue from '@vitejs/plugin-vue';
import VueMacros from 'unplugin-vue-macros/vite';
import reactivityTransform from '@vue-macros/reactivity-transform/vite';

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [
    VueMacros({
      plugins: {
        vue: Vue(),
        plugin: [],
      },
    }),
    reactivityTransform(),
  ],
});

我就知道评论区里有人又会说这样会增加心智负担,但是我觉得你的心智是不是太弱了,这样还有负担?

【实验】defineRender 让Vue更像React

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

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

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

<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。

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

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

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都省了,我把上面那个写法改一下,你们就知道了。

// Foo.setup.tsx
defineProps<{
  foo: string
}>()

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

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

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

以上就是关于你不知道的Vue最新功能:Vue Macros相关的全部内容,希望对你有帮助。欢迎持续关注程序员导航网,学习愉快哦!

版权声明:juejinhot 发表于 2024-04-13 19:26:30。
转载请注明:你不知道的Vue最新功能:Vue Macros | 程序员导航网

暂无评论

您必须登录才能参与评论!
立即登录
暂无评论...