本文主要讲解关于你不知道的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的配置
// 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相关的全部内容,希望对你有帮助。欢迎持续关注程序员导航网,学习愉快哦!