feat: v-model targe value should support variable

This commit is contained in:
Amour1688 2021-03-13 14:38:00 +08:00
parent 4c858a26e4
commit e9b83a0f96
5 changed files with 46 additions and 48 deletions

View File

@ -242,22 +242,23 @@ const buildProps = (path: NodePath<t.JSXElement>, state: State) => {
values.forEach((value, index) => { values.forEach((value, index) => {
const propName = args[index]; const propName = args[index];
// v-model target with variable // v-model target with variable
const isIdentifierProp = t.isIdentifier(propName); // const isIdentifierProp = t.isIdentifier(propName);
const isDynamic = !t.isStringLiteral(propName) && !t.isNullLiteral(propName);
// must be v-model or v-models and is a component // must be v-model or v-models and is a component
if (!directive) { if (!directive) {
properties.push( properties.push(
t.objectProperty(t.isNullLiteral(propName) t.objectProperty(t.isNullLiteral(propName)
? t.stringLiteral('modelValue') : propName, value as any, isIdentifierProp), ? t.stringLiteral('modelValue') : propName, value as any, isDynamic),
); );
if (!isIdentifierProp) { if (!isDynamic) {
dynamicPropNames.add((propName as t.StringLiteral)?.value || 'modelValue'); dynamicPropNames.add((propName as t.StringLiteral)?.value || 'modelValue');
} }
if (modifiers[index]?.size) { if (modifiers[index]?.size) {
properties.push( properties.push(
t.objectProperty( t.objectProperty(
isIdentifierProp isDynamic
? t.binaryExpression('+', propName, t.stringLiteral('Modifiers')) ? t.binaryExpression('+', propName, t.stringLiteral('Modifiers'))
: t.stringLiteral(`${(propName as t.StringLiteral)?.value || 'model'}Modifiers`), : t.stringLiteral(`${(propName as t.StringLiteral)?.value || 'model'}Modifiers`),
t.objectExpression( t.objectExpression(
@ -266,13 +267,13 @@ const buildProps = (path: NodePath<t.JSXElement>, state: State) => {
t.booleanLiteral(true), t.booleanLiteral(true),
)), )),
), ),
isIdentifierProp, isDynamic,
), ),
); );
} }
} }
const updateName = isIdentifierProp const updateName = isDynamic
? t.binaryExpression('+', t.stringLiteral('onUpdate'), propName) ? t.binaryExpression('+', t.stringLiteral('onUpdate'), propName)
: t.stringLiteral(`onUpdate:${(propName as t.StringLiteral)?.value || 'modelValue'}`); : t.stringLiteral(`onUpdate:${(propName as t.StringLiteral)?.value || 'modelValue'}`);
@ -283,11 +284,11 @@ const buildProps = (path: NodePath<t.JSXElement>, state: State) => {
[t.identifier('$event')], [t.identifier('$event')],
t.assignmentExpression('=', value as any, t.identifier('$event')), t.assignmentExpression('=', value as any, t.identifier('$event')),
), ),
isIdentifierProp, isDynamic,
), ),
); );
if (!isIdentifierProp) { if (!isDynamic) {
dynamicPropNames.add((updateName as t.StringLiteral).value); dynamicPropNames.add((updateName as t.StringLiteral).value);
} else { } else {
hasDynamicKeys = true; hasDynamicKeys = true;

View File

@ -34,7 +34,7 @@ const parseModifiers = (value: t.ArrayExpression): string[] => (
const parseDirectives = (params: { const parseDirectives = (params: {
name: string, name: string,
path: NodePath<t.JSXAttribute>, path: NodePath<t.JSXAttribute>,
value: t.StringLiteral | t.Expression | null, value: t.Expression | null,
state: State, state: State,
tag: Tag, tag: Tag,
isComponent: boolean isComponent: boolean
@ -42,7 +42,7 @@ const parseDirectives = (params: {
const { const {
name, path, value, state, tag, isComponent, name, path, value, state, tag, isComponent,
} = params; } = params;
const args: Array<t.StringLiteral | t.Identifier | t.NullLiteral> = []; const args: Array<t.Expression | t.NullLiteral> = [];
const vals: t.Expression[] = []; const vals: t.Expression[] = [];
const modifiersSet: Set<string>[] = []; const modifiersSet: Set<string>[] = [];
const underscoreModifiers = name.split('_'); const underscoreModifiers = name.split('_');
@ -77,7 +77,7 @@ const parseDirectives = (params: {
const [first, second, third] = elements; const [first, second, third] = elements;
let modifiers = underscoreModifiers; let modifiers = underscoreModifiers;
if (t.isStringLiteral(second) || t.isIdentifier(second)) { if (second && !t.isArrayExpression(second) && !t.isSpreadElement(second)) {
args.push(second); args.push(second);
modifiers = parseModifiers(third as t.ArrayExpression); modifiers = parseModifiers(third as t.ArrayExpression);
} else if (t.isArrayExpression(second)) { } else if (t.isArrayExpression(second)) {

View File

@ -266,27 +266,11 @@ exports[`v-model target value support variable: v-model target value support var
"import { createVNode as _createVNode, resolveComponent as _resolveComponent, Fragment as _Fragment } from \\"vue\\"; "import { createVNode as _createVNode, resolveComponent as _resolveComponent, Fragment as _Fragment } from \\"vue\\";
const foo = 'foo'; const foo = 'foo';
_createVNode(_Fragment, null, [_createVNode(_resolveComponent(\\"A\\"), { const a = () => 'a';
[foo]: xx,
[\\"onUpdate\\" + foo]: $event => xx = $event
}, null, 16), _createVNode(_resolveComponent(\\"B\\"), {
\\"modelValue\\": xx,
\\"modelModifiers\\": {
\\"a\\": true
},
\\"onUpdate:modelValue\\": $event => xx = $event
}, null, 8, [\\"modelValue\\", \\"onUpdate:modelValue\\"]), _createVNode(_resolveComponent(\\"C\\"), {
[foo]: xx,
[foo + \\"Modifiers\\"]: {
\\"a\\": true
},
[\\"onUpdate\\" + foo]: $event => xx = $event
}, null, 16)]);"
`;
exports[`v-models target value support variable: v-models target value support variable 1`] = ` const b = {
"import { createVNode as _createVNode, resolveComponent as _resolveComponent, Fragment as _Fragment } from \\"vue\\"; c: 'c'
const foo = 'foo'; };
_createVNode(_Fragment, null, [_createVNode(_resolveComponent(\\"A\\"), { _createVNode(_Fragment, null, [_createVNode(_resolveComponent(\\"A\\"), {
[foo]: xx, [foo]: xx,
@ -303,6 +287,24 @@ _createVNode(_Fragment, null, [_createVNode(_resolveComponent(\\"A\\"), {
\\"a\\": true \\"a\\": true
}, },
[\\"onUpdate\\" + foo]: $event => xx = $event [\\"onUpdate\\" + foo]: $event => xx = $event
}, null, 16), _createVNode(_resolveComponent(\\"D\\"), {
[foo === 'foo' ? 'a' : 'b']: xx,
[(foo === 'foo' ? 'a' : 'b') + \\"Modifiers\\"]: {
\\"a\\": true
},
[\\"onUpdate\\" + (foo === 'foo' ? 'a' : 'b')]: $event => xx = $event
}, null, 16), _createVNode(_resolveComponent(\\"E\\"), {
[a()]: xx,
[a() + \\"Modifiers\\"]: {
\\"a\\": true
},
[\\"onUpdate\\" + a()]: $event => xx = $event
}, null, 16), _createVNode(_resolveComponent(\\"F\\"), {
[b.c]: xx,
[b.c + \\"Modifiers\\"]: {
\\"a\\": true
},
[\\"onUpdate\\" + b.c]: $event => xx = $event
}, null, 16)]);" }, null, 16)]);"
`; `;

View File

@ -174,21 +174,17 @@ const tests: Test[] = [
name: 'v-model target value support variable', name: 'v-model target value support variable',
from: ` from: `
const foo = 'foo'; const foo = 'foo';
const a = () => 'a';
const b = { c: 'c' };
<> <>
<A v-model={[xx, foo]} /> <A v-model={[xx, foo]} />
<B v-model={[xx, ['a']]} /> <B v-model={[xx, ['a']]} />
<C v-model={[xx, foo, ['a']]} /> <C v-model={[xx, foo, ['a']]} />
</> <D v-model={[xx, foo === 'foo' ? 'a' : 'b', ['a']]} />
`, <E v-model={[xx, a(), ['a']]} />
}, <F v-model={[xx, b.c, ['a']]} />
{
name: 'v-models target value support variable',
from: `
const foo = 'foo';
<>
<A v-models={[[xx, foo]]} />
<B v-models={[[xx, ['a']]]} />
<C v-models={[[xx, foo, ['a']]]} />
</> </>
`, `,
}, },

View File

@ -22,11 +22,7 @@ interface PersistedState {
window.init = () => { window.init = () => {
const { monaco } = window; const { monaco } = window;
const persistedState: PersistedState = JSON.parse( const persistedState: PersistedState = JSON.parse(localStorage.getItem('state') || '{}');
decodeURIComponent(window.location.hash.slice(1))
|| localStorage.getItem('state')
|| '{}',
);
Object.assign(compilerOptions, persistedState.options); Object.assign(compilerOptions, persistedState.options);
@ -66,7 +62,10 @@ window.init = () => {
const reCompile = () => { const reCompile = () => {
const src = editor.getValue(); const src = editor.getValue();
const state = JSON.stringify(compilerOptions); const state = JSON.stringify({
src,
options: compilerOptions,
});
localStorage.setItem('state', state); localStorage.setItem('state', state);
window.location.hash = encodeURIComponent(src); window.location.hash = encodeURIComponent(src);
console.clear(); console.clear();