use createVNode (#14)

* chore: use createVNode

* test: add patchFlag
This commit is contained in:
Amour1688 2020-06-27 09:31:41 +08:00 committed by GitHub
parent ed66deccf6
commit a68a45e6ca
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 33 additions and 56 deletions

View File

@ -369,14 +369,14 @@ const transformJSXElement = (t, path, state) => {
const child = children.length === 1 && t.isStringLiteral(children[0]) const child = children.length === 1 && t.isStringLiteral(children[0])
? children[0] : t.arrayExpression(children); ? children[0] : t.arrayExpression(children);
const { compatibleProps, usePatchFlag } = state.opts; const { compatibleProps } = state.opts;
if (compatibleProps && !state.get('compatibleProps')) { if (compatibleProps && !state.get('compatibleProps')) {
state.set('compatibleProps', addDefault( state.set('compatibleProps', addDefault(
path, '@ant-design-vue/babel-helper-vue-compatible-props', { nameHint: '_compatibleProps' }, path, '@ant-design-vue/babel-helper-vue-compatible-props', { nameHint: '_compatibleProps' },
)); ));
} }
const createVNode = t.callExpression(createIdentifier(t, state, usePatchFlag ? 'createVNode' : 'h'), [ const createVNode = t.callExpression(createIdentifier(t, state, 'createVNode'), [
tag, tag,
compatibleProps ? t.callExpression(state.get('compatibleProps'), [props]) : props, compatibleProps ? t.callExpression(state.get('compatibleProps'), [props]) : props,
children[0] children[0]
@ -400,8 +400,8 @@ const transformJSXElement = (t, path, state) => {
]) ])
: child : child
) : t.nullLiteral(), ) : t.nullLiteral(),
patchFlag && usePatchFlag && t.addComment(t.numericLiteral(patchFlag), 'trailing', ` ${flagNames} `, false), patchFlag && t.addComment(t.numericLiteral(patchFlag), 'trailing', ` ${flagNames} `, false),
dynamicPropNames.size && usePatchFlag dynamicPropNames.size
&& t.arrayExpression([...dynamicPropNames.keys()].map((name) => t.stringLiteral(name))), && t.arrayExpression([...dynamicPropNames.keys()].map((name) => t.stringLiteral(name))),
].filter(Boolean)); ].filter(Boolean));

View File

@ -1,6 +1,12 @@
import { ref } from 'vue'; import { reactive, ref } from 'vue';
import { shallowMount, mount } from '@vue/test-utils'; import { shallowMount, mount } from '@vue/test-utils';
const patchFlagExpect = (wrapper, flag, dynamic) => {
const { patchFlag, dynamicProps } = wrapper.vm.$.subTree;
expect(patchFlag).toBe(flag);
expect(dynamicProps).toEqual(dynamic);
};
describe('Transform JSX', () => { describe('Transform JSX', () => {
test('should render with render function', () => { test('should render with render function', () => {
const wrapper = shallowMount({ const wrapper = shallowMount({
@ -52,6 +58,7 @@ describe('Transform JSX', () => {
); );
}, },
}); });
expect(wrapper.classes()).toStrictEqual([]);
expect(wrapper.text()).toBe('1'); expect(wrapper.text()).toBe('1');
}); });
@ -256,78 +263,48 @@ describe('Transform JSX', () => {
}); });
describe('PatchFlags', () => { describe('PatchFlags', () => {
let renders = 0; test('static', () => {
const Child = { const wrapper = shallowMount({
props: ['text'], setup() {
setup(props) { return () => <div class="static">static</div>;
return () => {
renders++;
return <div>{props.text}</div>;
};
}, },
}; });
Child.inheritAttrs = false; patchFlagExpect(wrapper, 0, null);
});
it('should render when props change', async () => { test('props', async () => {
const wrapper = mount({ const wrapper = mount({
setup() { setup() {
const count = ref(0); const visible = ref(true);
const inc = () => { const onClick = () => {
count.value++; visible.value = false;
}; };
return () => <div vShow={visible.value} onClick={onClick}>NEED_PATCH</div>;
},
});
patchFlagExpect(wrapper, 8, ['onClick']);
await wrapper.trigger('click');
expect(wrapper.html()).toBe('<div style="display: none;">NEED_PATCH</div>');
});
test('full props', async () => {
const wrapper = mount({
setup() {
const bindProps = reactive({ class: 'a', style: { marginTop: 10 } });
const onClick = () => {
bindProps.class = 'b';
};
return () => ( return () => (
<div onClick={inc}> <div {...bindProps} class="static" onClick={onClick}>full props</div>
<Child text={count.value} />
</div>
);
},
});
expect(renders).toBe(1);
await wrapper.trigger('click');
expect(renders).toBe(2);
});
it('should not render with static props', async () => {
renders = 0;
const wrapper = mount({
setup() {
const count = ref(0);
const inc = () => {
count.value++;
};
return () => (
<div onClick={inc}>
<Child text={1} />
</div>
);
},
});
expect(renders).toBe(1);
await wrapper.trigger('click');
expect(renders).toBe(1);
});
it('should not render when props does not change', async () => {
renders = 0;
const wrapper = mount({
setup() {
const count = ref(0);
const s = ref('a');
const inc = () => {
count.value++;
};
return () => (
<div onClick={inc}>
<Child text={s.value} />
{count.value}
</div>
); );
}, },
}); });
patchFlagExpect(wrapper, 16, ['onClick']);
await wrapper.trigger('click'); await wrapper.trigger('click');
expect(renders).toBe(1);
expect(wrapper.classes().sort()).toEqual(['b', 'static'].sort());
}); });
}); });