What is @vue/reactivity-transform?
The @vue/reactivity-transform package is part of the Vue.js ecosystem, designed to enhance the developer experience by providing syntactic sugar for the Vue Composition API. It allows developers to write reactive code in a more concise and readable manner by automatically wrapping reactive state and refs without the need for explicit calls to `ref()` or `reactive()` functions. This package leverages compile-time transformations to achieve this, making the code both cleaner and easier to understand.
What are @vue/reactivity-transform's main functionalities?
Automatic Ref Creation
Automatically creates a Vue ref (reactive reference) from a simple assignment. This eliminates the need to explicitly call `ref()` from Vue's Composition API, making the code cleaner and more intuitive.
let count = $ref(0);
function increment() {
count++;
}
Reactive Declarations
Enables the creation of computed properties in a more concise way. By using `$computed`, it simplifies the syntax required to declare reactive computed properties, making the code more readable.
let doubled = $computed(() => count * 2);
Reactive Effects
Facilitates the creation of side effects that automatically track reactive dependencies. Using `$effect`, developers can easily define behavior that responds to changes in reactive data, without the boilerplate code typically associated with setting up watchers.
$effect(() => {
console.log(`count is: ${count}`);
});
Other packages similar to @vue/reactivity-transform
mobx
MobX is a state management library that also focuses on making state as reactive as possible. It differs from @vue/reactivity-transform in that it's not tied to the Vue ecosystem and offers its own set of APIs for creating observables, computed values, and reactions. MobX can be used with any framework, making it more versatile, but potentially more verbose for Vue-specific projects.
immer
Immer is a package that allows you to work with immutable state in a more convenient way. While it doesn't offer reactive programming features out of the box like @vue/reactivity-transform, it simplifies the process of updating complex state objects in an immutable manner. Immer is framework-agnostic and focuses on producing the next immutable state by applying a draft state, which is a different approach compared to the reactive transformations provided by @vue/reactivity-transform.
@vue/reactivity-transform
⚠️ This is experimental and currently only provided for testing and feedback. It may break during patches or even be removed. Use at your own risk!
Follow https://github.com/vuejs/rfcs/discussions/369 for details and updates.
Basic Rules
- Ref-creating APIs have
$
-prefixed versions that create reactive variables instead. They also do not need to be explicitly imported. These include:
ref
computed
shallowRef
customRef
toRef
$()
can be used to destructure an object into reactive variables, or turn existing refs into reactive variables$$()
to "escape" the transform, which allows access to underlying refs
import { watchEffect } from 'vue'
let count = $ref(0)
watchEffect(() => {
console.log(count)
})
count++
console.log($$(count))
Macros can be optionally imported to make it more explicit:
import { $, $ref } from 'vue/macros'
let count = $ref(0)
const { x, y } = $(useMouse())
Global Types
To enable types for the macros globally, include the following in a .d.ts
file:
API
This package is the lower-level transform that can be used standalone. Higher-level tooling (e.g. @vitejs/plugin-vue
and vue-loader
) will provide integration via options.
shouldTransform
Can be used to do a cheap check to determine whether full transform should be performed.
import { shouldTransform } from '@vue/reactivity-transform'
shouldTransform(`let a = ref(0)`)
shouldTransform(`let a = $ref(0)`)
transform
import { transform } from '@vue/reactivity-transform'
const src = `let a = $ref(0); a++`
const {
code,
map
} = transform(src, {
filename: 'foo.ts',
sourceMap: true,
parserPlugins: [
]
})
Options
interface RefTransformOptions {
filename?: string
sourceMap?: boolean
parserPlugins?: ParserPlugin[]
importHelpersFrom?: string
}
transformAST
Transform with an existing Babel AST + MagicString instance. This is used internally by @vue/compiler-sfc
to avoid double parse/transform cost.
import { transformAST } from '@vue/reactivity-transform'
import { parse } from '@babel/parser'
import MagicString from 'magic-string'
const src = `let a = $ref(0); a++`
const ast = parse(src, { sourceType: 'module' })
const s = new MagicString(src)
const {
rootRefs,
importedHelpers
} = transformAST(ast, s)
console.log(s.toString())