mirror of
https://github.com/vuejs/babel-plugin-jsx.git
synced 2025-03-13 14:14:40 +08:00
fix: component doesn't render when variables outside slot
This commit is contained in:
parent
5c59e2e27b
commit
9454655ee7
@ -12,6 +12,7 @@ import {
|
||||
transformJSXExpressionContainer,
|
||||
parseDirectives,
|
||||
isFragment,
|
||||
walksScope,
|
||||
} from './utils';
|
||||
import { PatchFlags, PatchFlagNames } from './patchFlags';
|
||||
import { State, ExcludesBoolean } from './';
|
||||
@ -22,13 +23,17 @@ const onRE = /^on[^a-z]/;
|
||||
const isOn = (key: string) => onRE.test(key);
|
||||
|
||||
const transformJSXSpreadAttribute = (
|
||||
nodePath: NodePath,
|
||||
path: NodePath<t.JSXSpreadAttribute>,
|
||||
mergeArgs: (t.ObjectProperty | t.Expression)[]
|
||||
) => {
|
||||
const argument = path.get('argument') as NodePath<t.ObjectExpression>;
|
||||
const { properties } = argument.node;
|
||||
if (!properties) {
|
||||
// argument is an Identifier
|
||||
if (argument.isIdentifier()) {
|
||||
console.log(isConstant(argument.node), argument.node)
|
||||
walksScope(nodePath, (argument.node as t.Identifier).name);
|
||||
}
|
||||
mergeArgs.push(argument.node);
|
||||
} else {
|
||||
mergeArgs.push(t.objectExpression(properties));
|
||||
@ -257,7 +262,7 @@ const buildProps = (path: NodePath<t.JSXElement>, state: State) => {
|
||||
} else {
|
||||
// JSXSpreadAttribute
|
||||
hasDynamicKeys = true;
|
||||
transformJSXSpreadAttribute(prop as NodePath<t.JSXSpreadAttribute>, mergeArgs);
|
||||
transformJSXSpreadAttribute(path as NodePath, prop as NodePath<t.JSXSpreadAttribute>, mergeArgs);
|
||||
}
|
||||
});
|
||||
|
||||
@ -386,11 +391,7 @@ const transformJSXElement = (
|
||||
slots
|
||||
} = buildProps(path, state);
|
||||
|
||||
const { scope: { bindings } } = path;
|
||||
|
||||
const bindingsReferenced = Object.keys(bindings).some(key => bindings[key].referenced);
|
||||
|
||||
const useOptimate = !(bindingsReferenced && t.isReturnStatement(path.container));
|
||||
const useOptimate = path.getData('optimize') !== false;
|
||||
|
||||
const flagNames = Object.keys(PatchFlagNames)
|
||||
.map(Number)
|
||||
@ -411,7 +412,7 @@ const transformJSXElement = (
|
||||
// @ts-ignore
|
||||
compatibleProps ? t.callExpression(state.get('compatibleProps'), [props]) : props,
|
||||
(children.length || slots) ? (
|
||||
isComponent && (children.length || slots)
|
||||
isComponent
|
||||
? t.objectExpression([
|
||||
!!children.length && t.objectProperty(
|
||||
t.identifier('default'),
|
||||
|
@ -274,6 +274,13 @@ const parseDirectives = (args: {
|
||||
};
|
||||
};
|
||||
|
||||
const walksScope = (path: NodePath, name: string) => {
|
||||
if (path.scope.hasBinding(name)) {
|
||||
path.parentPath.setData('optimize', false);
|
||||
walksScope(path.parentPath, name);
|
||||
}
|
||||
}
|
||||
|
||||
export {
|
||||
createIdentifier,
|
||||
isDirective,
|
||||
@ -286,4 +293,5 @@ export {
|
||||
transformJSXExpressionContainer,
|
||||
parseDirectives,
|
||||
isFragment,
|
||||
walksScope,
|
||||
};
|
||||
|
@ -266,35 +266,39 @@ describe('Transform JSX', () => {
|
||||
describe('slots', () => {
|
||||
test('with default', () => {
|
||||
const A = (_, { slots }) => (
|
||||
<>
|
||||
<div>
|
||||
{slots.default()}
|
||||
{slots.foo('val')}
|
||||
</>
|
||||
</div>
|
||||
);
|
||||
|
||||
A.inheritAttrs = false;
|
||||
|
||||
const wrapper = mount({
|
||||
setup() {
|
||||
const slots = {
|
||||
foo: (val) => <div>{val}</div>,
|
||||
foo: (val) => val,
|
||||
};
|
||||
return () => <A vSlots={slots}><span>default</span></A>;
|
||||
},
|
||||
});
|
||||
|
||||
expect(wrapper.html()).toBe('<span>default</span><div>val</div>');
|
||||
expect(wrapper.html()).toBe('<div><span>default</span>val</div>');
|
||||
});
|
||||
|
||||
test('without default', () => {
|
||||
const A = (_, { slots }) => (
|
||||
<>
|
||||
<div>
|
||||
{slots.foo('foo')}
|
||||
</>
|
||||
</div>
|
||||
);
|
||||
|
||||
A.inheritAttrs = false;
|
||||
|
||||
const wrapper = mount({
|
||||
setup() {
|
||||
const slots = {
|
||||
foo: (val) => <div>{val}</div>,
|
||||
foo: (val) => val,
|
||||
};
|
||||
return () => <A vSlots={slots} />;
|
||||
},
|
||||
@ -349,4 +353,45 @@ describe('PatchFlags', () => {
|
||||
|
||||
expect(wrapper.classes().sort()).toEqual(['b', 'static'].sort());
|
||||
});
|
||||
|
||||
test('variables outside slot', async () => {
|
||||
const A = {
|
||||
render() {
|
||||
return this.$slots.default();
|
||||
},
|
||||
};
|
||||
|
||||
A.inheritAttrs = false;
|
||||
|
||||
const wrapper = mount({
|
||||
data() {
|
||||
return {
|
||||
val: 0,
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
inc() {
|
||||
this.val += 1;
|
||||
},
|
||||
},
|
||||
render() {
|
||||
const attrs = {
|
||||
innerHTML: this.val,
|
||||
};
|
||||
return (
|
||||
<A inc={this.inc}>
|
||||
<div>
|
||||
<textarea id="textarea" {...attrs} />
|
||||
</div>
|
||||
<button id="button" onClick={this.inc}>+1</button>
|
||||
</A>
|
||||
);
|
||||
},
|
||||
});
|
||||
|
||||
expect(wrapper.get('#textarea').element.innerHTML).toBe('0');
|
||||
|
||||
await wrapper.get('#button').trigger('click');
|
||||
expect(wrapper.get('#textarea').element.innerHTML).toBe('1');
|
||||
});
|
||||
});
|
||||
|
Loading…
x
Reference in New Issue
Block a user