fix: child nodes of KeepAlive should not be transformed to slots

This commit is contained in:
Amour1688 2021-02-04 22:18:07 +08:00
parent ee3faaf58b
commit f1c9629b88
4 changed files with 26 additions and 40 deletions

View File

@ -27,8 +27,8 @@ const getJSXAttributeValue = (
path: NodePath<t.JSXAttribute>, path: NodePath<t.JSXAttribute>,
state: State, state: State,
): ( ): (
t.StringLiteral | t.Expression | null t.StringLiteral | t.Expression | null
) => { ) => {
const valuePath = path.get('value'); const valuePath = path.get('value');
if (valuePath.isJSXElement()) { if (valuePath.isJSXElement()) {
return transformJSXElement(valuePath, state); return transformJSXElement(valuePath, state);
@ -181,8 +181,8 @@ const buildProps = (path: NodePath<t.JSXElement>, state: State) => {
hasStyleBinding = true; hasStyleBinding = true;
} else if ( } else if (
name !== 'key' name !== 'key'
&& !isDirective(name) && !isDirective(name)
&& name !== 'on' && name !== 'on'
) { ) {
dynamicPropNames.add(name); dynamicPropNames.add(name);
} }

View File

@ -20,18 +20,15 @@ export default ({
JSXFragment: { JSXFragment: {
enter(path: NodePath<t.JSXElement>, state: State) { enter(path: NodePath<t.JSXElement>, state: State) {
const fragmentCallee = createIdentifier(state, FRAGMENT); const fragmentCallee = createIdentifier(state, FRAGMENT);
path.replaceWith( path.replaceWith(transformFragment(
t.inherits(transformFragment( path,
path, t.isIdentifier(fragmentCallee)
t.isIdentifier(fragmentCallee) ? t.jsxIdentifier(fragmentCallee.name)
? t.jsxIdentifier(fragmentCallee.name) : t.jsxMemberExpression(
: t.jsxMemberExpression( t.jsxIdentifier((fragmentCallee.object as t.Identifier).name),
t.jsxIdentifier((fragmentCallee.object as t.Identifier).name), t.jsxIdentifier((fragmentCallee.property as t.Identifier).name),
t.jsxIdentifier((fragmentCallee.property as t.Identifier).name), ),
), ));
), path.node)
,
);
}, },
}, },
}); });

View File

@ -121,7 +121,7 @@ const transformJSXElement = (
t.numericLiteral(slotFlag), t.numericLiteral(slotFlag),
) as any, ) as any,
].filter(Boolean)); ].filter(Boolean));
if (t.isIdentifier(child)) { if (t.isIdentifier(child) && isComponent) {
VNodeChild = enableObjectSlots ? t.conditionalExpression( VNodeChild = enableObjectSlots ? t.conditionalExpression(
t.callExpression(state.get('@vue/babel-plugin-jsx/runtimeIsSlot')(), [child]), t.callExpression(state.get('@vue/babel-plugin-jsx/runtimeIsSlot')(), [child]),
child, child,
@ -212,9 +212,7 @@ export { transformJSXElement };
export default ({ export default ({
JSXElement: { JSXElement: {
exit(path: NodePath<t.JSXElement>, state: State) { exit(path: NodePath<t.JSXElement>, state: State) {
path.replaceWith( path.replaceWith(transformJSXElement(path, state));
t.inherits(transformJSXElement(path, state), path.node),
);
}, },
}, },
}); });

View File

@ -7,6 +7,8 @@ import SlotFlags from './slotFlags';
const JSX_HELPER_KEY = 'JSX_HELPER_KEY'; const JSX_HELPER_KEY = 'JSX_HELPER_KEY';
const FRAGMENT = 'Fragment'; const FRAGMENT = 'Fragment';
const KEEP_ALIVE = 'KeepAlive';
/** /**
* create Identifier * create Identifier
* @param path NodePath * @param path NodePath
@ -26,22 +28,11 @@ const isDirective = (src: string): boolean => src.startsWith('v-')
|| (src.startsWith('v') && src.length >= 2 && src[1] >= 'A' && src[1] <= 'Z'); || (src.startsWith('v') && src.length >= 2 && src[1] >= 'A' && src[1] <= 'Z');
/** /**
* Check if a Node is fragment * Should transformed to slots
* @param {*} path JSXIdentifier | JSXMemberExpression | JSXNamespacedName * @param tag string
* @returns boolean * @returns boolean
*/ */
const isFragment = ( const shouldTransformedToSlots = (tag: string) => !(tag.endsWith(FRAGMENT) || tag === KEEP_ALIVE);
path:
NodePath<t.JSXIdentifier | t.JSXMemberExpression | t.JSXNamespacedName>,
): boolean => {
if (path.isJSXIdentifier()) {
return path.node.name.endsWith(FRAGMENT);
}
if (path.isJSXMemberExpression()) {
return path.node.property.name.endsWith(FRAGMENT);
}
return false;
};
/** /**
* Check if a Node is a component * Check if a Node is a component
@ -53,13 +44,13 @@ const isFragment = (
const checkIsComponent = (path: NodePath<t.JSXOpeningElement>): boolean => { const checkIsComponent = (path: NodePath<t.JSXOpeningElement>): boolean => {
const namePath = path.get('name'); const namePath = path.get('name');
if (t.isJSXMemberExpression(namePath)) { if (namePath.isJSXMemberExpression()) {
return !isFragment(namePath); // For withCtx return shouldTransformedToSlots(namePath.node.property.name); // For withCtx
} }
const tag = (namePath as NodePath<t.JSXIdentifier>).node.name; const tag = (namePath as NodePath<t.JSXIdentifier>).node.name;
return !tag.endsWith(FRAGMENT) && !htmlTags.includes(tag) && !svgTags.includes(tag); return shouldTransformedToSlots(tag) && !htmlTags.includes(tag) && !svgTags.includes(tag);
}; };
/** /**
@ -181,8 +172,8 @@ const transformJSXText = (path: NodePath<t.JSXText>): t.StringLiteral | null =>
const transformJSXExpressionContainer = ( const transformJSXExpressionContainer = (
path: NodePath<t.JSXExpressionContainer>, path: NodePath<t.JSXExpressionContainer>,
): ( ): (
t.Expression t.Expression
) => path.get('expression').node as t.Expression; ) => path.get('expression').node as t.Expression;
/** /**
* Transform JSXSpreadChild * Transform JSXSpreadChild
@ -240,7 +231,7 @@ export {
transformJSXText, transformJSXText,
transformJSXSpreadChild, transformJSXSpreadChild,
transformJSXExpressionContainer, transformJSXExpressionContainer,
isFragment, shouldTransformedToSlots,
FRAGMENT, FRAGMENT,
walksScope, walksScope,
buildIIFE, buildIIFE,