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) => {
const propName = args[index];
// 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
if (!directive) {
properties.push(
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');
}
if (modifiers[index]?.size) {
properties.push(
t.objectProperty(
isIdentifierProp
isDynamic
? t.binaryExpression('+', propName, t.stringLiteral('Modifiers'))
: t.stringLiteral(`${(propName as t.StringLiteral)?.value || 'model'}Modifiers`),
t.objectExpression(
@ -266,13 +267,13 @@ const buildProps = (path: NodePath<t.JSXElement>, state: State) => {
t.booleanLiteral(true),
)),
),
isIdentifierProp,
isDynamic,
),
);
}
}
const updateName = isIdentifierProp
const updateName = isDynamic
? t.binaryExpression('+', t.stringLiteral('onUpdate'), propName)
: 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.assignmentExpression('=', value as any, t.identifier('$event')),
),
isIdentifierProp,
isDynamic,
),
);
if (!isIdentifierProp) {
if (!isDynamic) {
dynamicPropNames.add((updateName as t.StringLiteral).value);
} else {
hasDynamicKeys = true;

View File

@ -34,7 +34,7 @@ const parseModifiers = (value: t.ArrayExpression): string[] => (
const parseDirectives = (params: {
name: string,
path: NodePath<t.JSXAttribute>,
value: t.StringLiteral | t.Expression | null,
value: t.Expression | null,
state: State,
tag: Tag,
isComponent: boolean
@ -42,7 +42,7 @@ const parseDirectives = (params: {
const {
name, path, value, state, tag, isComponent,
} = params;
const args: Array<t.StringLiteral | t.Identifier | t.NullLiteral> = [];
const args: Array<t.Expression | t.NullLiteral> = [];
const vals: t.Expression[] = [];
const modifiersSet: Set<string>[] = [];
const underscoreModifiers = name.split('_');
@ -77,7 +77,7 @@ const parseDirectives = (params: {
const [first, second, third] = elements;
let modifiers = underscoreModifiers;
if (t.isStringLiteral(second) || t.isIdentifier(second)) {
if (second && !t.isArrayExpression(second) && !t.isSpreadElement(second)) {
args.push(second);
modifiers = parseModifiers(third as t.ArrayExpression);
} 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\\";
const foo = 'foo';
_createVNode(_Fragment, null, [_createVNode(_resolveComponent(\\"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)]);"
`;
const a = () => 'a';
exports[`v-models target value support variable: v-models target value support variable 1`] = `
"import { createVNode as _createVNode, resolveComponent as _resolveComponent, Fragment as _Fragment } from \\"vue\\";
const foo = 'foo';
const b = {
c: 'c'
};
_createVNode(_Fragment, null, [_createVNode(_resolveComponent(\\"A\\"), {
[foo]: xx,
@ -303,6 +287,24 @@ _createVNode(_Fragment, null, [_createVNode(_resolveComponent(\\"A\\"), {
\\"a\\": true
},
[\\"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)]);"
`;

View File

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

View File

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