fix: component doesn't render when variables outside slot

This commit is contained in:
Amour1688 2020-07-12 10:19:31 +08:00
parent 5c59e2e27b
commit 9454655ee7
3 changed files with 69 additions and 15 deletions

View File

@ -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'),

View File

@ -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,
};

View File

@ -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');
});
});