你不知道的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的写法呢?

相关推荐
一路向前的月光1 小时前
Vue2中的监听和计算属性的区别
前端·javascript·vue.js
长路 ㅤ   1 小时前
vue-live2d看板娘集成方案设计使用教程
前端·javascript·vue.js·live2d
Fan_web1 小时前
jQuery——事件委托
开发语言·前端·javascript·css·jquery
Jiaberrr2 小时前
Element UI教程:如何将Radio单选框的圆框改为方框
前端·javascript·vue.js·ui·elementui
安冬的码畜日常4 小时前
【D3.js in Action 3 精译_029】3.5 给 D3 条形图加注图表标签(上)
开发语言·前端·javascript·信息可视化·数据可视化·d3.js
太阳花ˉ4 小时前
html+css+js实现step进度条效果
javascript·css·html
程序员大金5 小时前
基于SpringBoot+Vue+MySQL的装修公司管理系统
vue.js·spring boot·mysql
john_hjy5 小时前
11. 异步编程
运维·服务器·javascript
风清扬_jd5 小时前
Chromium 中JavaScript Fetch API接口c++代码实现(二)
javascript·c++·chrome