feat(sfc): support $shallowRef ref sugar
This commit is contained in:
parent
e42d7794cb
commit
00b76d3dc1
@ -33,8 +33,8 @@ return { a, b, c }
|
|||||||
}"
|
}"
|
||||||
`;
|
`;
|
||||||
|
|
||||||
exports[`<script setup> ref sugar $ref declarations 1`] = `
|
exports[`<script setup> ref sugar $ref & $shallowRef declarations 1`] = `
|
||||||
"import { ref as _ref } from 'vue'
|
"import { ref as _ref, shallowRef as _shallowRef } from 'vue'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
setup(__props, { expose }) {
|
setup(__props, { expose }) {
|
||||||
@ -42,7 +42,7 @@ export default {
|
|||||||
|
|
||||||
let foo = _ref()
|
let foo = _ref()
|
||||||
let a = _ref(1)
|
let a = _ref(1)
|
||||||
let b = _ref({
|
let b = _shallowRef({
|
||||||
count: 0
|
count: 0
|
||||||
})
|
})
|
||||||
let c = () => {}
|
let c = () => {}
|
||||||
|
@ -6,24 +6,26 @@ describe('<script setup> ref sugar', () => {
|
|||||||
return compile(src, { refSugar: true })
|
return compile(src, { refSugar: true })
|
||||||
}
|
}
|
||||||
|
|
||||||
test('$ref declarations', () => {
|
test('$ref & $shallowRef declarations', () => {
|
||||||
const { content, bindings } = compileWithRefSugar(`<script setup>
|
const { content, bindings } = compileWithRefSugar(`<script setup>
|
||||||
let foo = $ref()
|
let foo = $ref()
|
||||||
let a = $ref(1)
|
let a = $ref(1)
|
||||||
let b = $ref({
|
let b = $shallowRef({
|
||||||
count: 0
|
count: 0
|
||||||
})
|
})
|
||||||
let c = () => {}
|
let c = () => {}
|
||||||
let d
|
let d
|
||||||
</script>`)
|
</script>`)
|
||||||
expect(content).toMatch(`import { ref as _ref } from 'vue'`)
|
expect(content).toMatch(
|
||||||
|
`import { ref as _ref, shallowRef as _shallowRef } from 'vue'`
|
||||||
|
)
|
||||||
expect(content).not.toMatch(`$ref()`)
|
expect(content).not.toMatch(`$ref()`)
|
||||||
expect(content).not.toMatch(`$ref(1)`)
|
expect(content).not.toMatch(`$ref(1)`)
|
||||||
expect(content).not.toMatch(`$ref({`)
|
expect(content).not.toMatch(`$shallowRef({`)
|
||||||
expect(content).toMatch(`let foo = _ref()`)
|
expect(content).toMatch(`let foo = _ref()`)
|
||||||
expect(content).toMatch(`let a = _ref(1)`)
|
expect(content).toMatch(`let a = _ref(1)`)
|
||||||
expect(content).toMatch(`
|
expect(content).toMatch(`
|
||||||
let b = _ref({
|
let b = _shallowRef({
|
||||||
count: 0
|
count: 0
|
||||||
})
|
})
|
||||||
`)
|
`)
|
||||||
|
@ -65,6 +65,7 @@ const DEFINE_EXPOSE = 'defineExpose'
|
|||||||
const WITH_DEFAULTS = 'withDefaults'
|
const WITH_DEFAULTS = 'withDefaults'
|
||||||
|
|
||||||
const $REF = `$ref`
|
const $REF = `$ref`
|
||||||
|
const $SHALLOW_REF = '$shallowRef'
|
||||||
const $COMPUTED = `$computed`
|
const $COMPUTED = `$computed`
|
||||||
const $FROM_REFS = `$fromRefs`
|
const $FROM_REFS = `$fromRefs`
|
||||||
const $RAW = `$raw`
|
const $RAW = `$raw`
|
||||||
@ -531,7 +532,12 @@ export function compileScript(
|
|||||||
}
|
}
|
||||||
|
|
||||||
function isRefSugarCall(callee: string) {
|
function isRefSugarCall(callee: string) {
|
||||||
return callee === $REF || callee === $COMPUTED || callee === $FROM_REFS
|
return (
|
||||||
|
callee === $REF ||
|
||||||
|
callee === $COMPUTED ||
|
||||||
|
callee === $FROM_REFS ||
|
||||||
|
callee === $SHALLOW_REF
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
function processRefSugar(
|
function processRefSugar(
|
||||||
@ -558,24 +564,28 @@ export function compileScript(
|
|||||||
|
|
||||||
const callee = (decl.init.callee as Identifier).name
|
const callee = (decl.init.callee as Identifier).name
|
||||||
const start = decl.init.start! + startOffset
|
const start = decl.init.start! + startOffset
|
||||||
if (callee === $REF) {
|
if (callee === $REF || callee === $SHALLOW_REF) {
|
||||||
if (statement.kind !== 'let') {
|
if (statement.kind !== 'let') {
|
||||||
error(`${$REF}() bindings can only be declared with let.`, decl)
|
error(`${callee}() bindings can only be declared with let.`, decl)
|
||||||
}
|
}
|
||||||
if (decl.id.type !== 'Identifier') {
|
if (decl.id.type !== 'Identifier') {
|
||||||
error(
|
error(
|
||||||
`${$REF}() bindings cannot be used with destructuring. ` +
|
`${callee}() bindings cannot be used with destructuring. ` +
|
||||||
`If you are trying to destructure from an object of refs, ` +
|
`If you are trying to destructure from an object of refs, ` +
|
||||||
`use \`let { x } = $fromRefs(obj)\`.`,
|
`use \`let { x } = $fromRefs(obj)\`.`,
|
||||||
decl.id
|
decl.id
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
registerRefBinding(decl.id)
|
registerRefBinding(decl.id)
|
||||||
s.overwrite(start, start + $REF.length, helper('ref'))
|
s.overwrite(
|
||||||
|
start,
|
||||||
|
start + callee.length,
|
||||||
|
helper(callee === $REF ? 'ref' : 'shallowRef')
|
||||||
|
)
|
||||||
} else if (callee === $COMPUTED) {
|
} else if (callee === $COMPUTED) {
|
||||||
if (decl.id.type !== 'Identifier') {
|
if (decl.id.type !== 'Identifier') {
|
||||||
error(
|
error(
|
||||||
`${$COMPUTED}() bindings cannot be used with destructuring.`,
|
`${callee}() bindings cannot be used with destructuring.`,
|
||||||
decl.id
|
decl.id
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -584,7 +594,7 @@ export function compileScript(
|
|||||||
} else if (callee === $FROM_REFS) {
|
} else if (callee === $FROM_REFS) {
|
||||||
if (!decl.id.type.endsWith('Pattern')) {
|
if (!decl.id.type.endsWith('Pattern')) {
|
||||||
error(
|
error(
|
||||||
`${$FROM_REFS}() declaration must be used with destructure patterns.`,
|
`${callee}() declaration must be used with destructure patterns.`,
|
||||||
decl
|
decl
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -1124,10 +1134,7 @@ export function compileScript(
|
|||||||
return false // skip walk
|
return false // skip walk
|
||||||
} else if (
|
} else if (
|
||||||
parent &&
|
parent &&
|
||||||
isCallOf(
|
isCallOf(node, isRefSugarCall) &&
|
||||||
node,
|
|
||||||
id => id === $REF || id === $FROM_REFS || id === $COMPUTED
|
|
||||||
) &&
|
|
||||||
(parent.type !== 'VariableDeclarator' || node !== parent.init)
|
(parent.type !== 'VariableDeclarator' || node !== parent.init)
|
||||||
) {
|
) {
|
||||||
error(
|
error(
|
||||||
|
@ -3,6 +3,10 @@ import { Ref, UnwrapRef, ShallowUnwrapRef, ComputedRef } from '@vue/reactivity'
|
|||||||
export function $ref<T>(arg: T | Ref<T>): UnwrapRef<T>
|
export function $ref<T>(arg: T | Ref<T>): UnwrapRef<T>
|
||||||
export function $ref() {}
|
export function $ref() {}
|
||||||
|
|
||||||
|
export function $shallowRef<T>(arg: T): T {
|
||||||
|
return arg
|
||||||
|
}
|
||||||
|
|
||||||
declare const ComputedRefMarker: unique symbol
|
declare const ComputedRefMarker: unique symbol
|
||||||
type ComputedRefValue<T> = T & { [ComputedRefMarker]?: any }
|
type ComputedRefValue<T> = T & { [ComputedRefMarker]?: any }
|
||||||
|
|
||||||
|
@ -354,4 +354,10 @@ export const compatUtils = (
|
|||||||
|
|
||||||
// Ref sugar macros ------------------------------------------------------------
|
// Ref sugar macros ------------------------------------------------------------
|
||||||
// for dts generation only
|
// for dts generation only
|
||||||
export { $ref, $computed, $raw, $fromRefs } from './helpers/refSugar'
|
export {
|
||||||
|
$ref,
|
||||||
|
$shallowRef,
|
||||||
|
$computed,
|
||||||
|
$raw,
|
||||||
|
$fromRefs
|
||||||
|
} from './helpers/refSugar'
|
||||||
|
@ -6,6 +6,7 @@ type _defineExpose = typeof defineExpose
|
|||||||
type _withDefaults = typeof withDefaults
|
type _withDefaults = typeof withDefaults
|
||||||
|
|
||||||
type _ref = typeof $ref
|
type _ref = typeof $ref
|
||||||
|
type _shallowRef = typeof $shallowRef
|
||||||
type _computed = typeof $computed
|
type _computed = typeof $computed
|
||||||
type _fromRefs = typeof $fromRefs
|
type _fromRefs = typeof $fromRefs
|
||||||
type _raw = typeof $raw
|
type _raw = typeof $raw
|
||||||
@ -17,6 +18,7 @@ declare global {
|
|||||||
const withDefaults: _withDefaults
|
const withDefaults: _withDefaults
|
||||||
|
|
||||||
const $ref: _ref
|
const $ref: _ref
|
||||||
|
const $shallowRef: _shallowRef
|
||||||
const $computed: _computed
|
const $computed: _computed
|
||||||
const $fromRefs: _fromRefs
|
const $fromRefs: _fromRefs
|
||||||
const $raw: _raw
|
const $raw: _raw
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import {
|
import {
|
||||||
expectType,
|
expectType,
|
||||||
$ref,
|
$ref,
|
||||||
|
$shallowRef,
|
||||||
$computed,
|
$computed,
|
||||||
$fromRefs,
|
$fromRefs,
|
||||||
$raw,
|
$raw,
|
||||||
@ -14,6 +15,10 @@ expectType<number>($ref(1))
|
|||||||
expectType<number>($ref(ref(1)))
|
expectType<number>($ref(ref(1)))
|
||||||
expectType<{ foo: number }>($ref({ foo: ref(1) }))
|
expectType<{ foo: number }>($ref({ foo: ref(1) }))
|
||||||
|
|
||||||
|
// $shallowRef
|
||||||
|
expectType<number>($shallowRef(1))
|
||||||
|
expectType<{ foo: Ref<number> }>($shallowRef({ foo: ref(1) }))
|
||||||
|
|
||||||
// $computed
|
// $computed
|
||||||
expectType<number>($computed(() => 1))
|
expectType<number>($computed(() => 1))
|
||||||
let b = $ref(1)
|
let b = $ref(1)
|
||||||
|
Loading…
Reference in New Issue
Block a user