perf: add event props

pull/2682/head
tanjinzhou 2020-08-05 17:17:07 +08:00
parent 36ee580f72
commit 532f51fc90
10 changed files with 84 additions and 108 deletions

@ -1 +1 @@
Subproject commit 60cb5c8b276b8d5a8c7fc9f8cb39053a14e242ee
Subproject commit 3978ece8febab44f9007ea66df2adc20d65982c4

View File

@ -16,6 +16,7 @@ export default {
checked: PropTypes.bool,
prefixCls: PropTypes.string,
disabled: PropTypes.bool,
onClick: PropTypes.func,
},
render() {
const { renderedText, renderedEl, item, lazy, checked, disabled, prefixCls } = this.$props;

View File

@ -3,22 +3,26 @@
exports[`Transfer should render correctly 1`] = `
<div class="ant-transfer">
<div class="ant-transfer-list">
<div class="ant-transfer-list-header"><label class="ant-checkbox-wrapper ant-checkbox-wrapper-checked"><span class="ant-checkbox ant-checkbox-checked"><input type="checkbox" checked="checked" class="ant-checkbox-input"><span class="ant-checkbox-inner"></span></span></label><span class="ant-transfer-list-header-selected"><span>1/2 items</span><span class="ant-transfer-list-header-title"></span></span></div>
<div class="ant-transfer-list-header"><label class="ant-checkbox-wrapper ant-checkbox-wrapper-checked"><span class="ant-checkbox ant-checkbox-checked"><input type="checkbox" class="ant-checkbox-input" value=""><span class="ant-checkbox-inner"></span></span><span></span></label><span class="ant-transfer-list-header-selected"><span>1/2 items</span><span class="ant-transfer-list-header-title"></span></span></div>
<div class="ant-transfer-list-body">
<!---->
<ul class="ant-transfer-list-content">
<li class="ant-transfer-list-content-item"><label class="ant-checkbox-wrapper ant-checkbox-wrapper-checked"><span class="ant-checkbox ant-checkbox-checked"><input type="checkbox" checked="checked" class="ant-checkbox-input"><span class="ant-checkbox-inner"></span></span></label><span class="ant-transfer-list-content-item-text"></span></li>
<li class="ant-transfer-list-content-item ant-transfer-list-content-item-disabled"><label class="ant-checkbox-wrapper ant-checkbox-wrapper-disabled"><span class="ant-checkbox ant-checkbox-disabled"><input type="checkbox" disabled="disabled" class="ant-checkbox-input"><span class="ant-checkbox-inner"></span></span></label><span class="ant-transfer-list-content-item-text"></span></li>
<li class="ant-transfer-list-content-item"><label class="ant-checkbox-wrapper ant-checkbox-wrapper-checked"><span class="ant-checkbox ant-checkbox-checked"><input type="checkbox" class="ant-checkbox-input" value=""><span class="ant-checkbox-inner"></span></span><span></span></label><span class="ant-transfer-list-content-item-text"><!----></span></li>
<li class="ant-transfer-list-content-item ant-transfer-list-content-item-disabled"><label class="ant-checkbox-wrapper ant-checkbox-wrapper-disabled"><span class="ant-checkbox ant-checkbox-disabled"><input type="checkbox" disabled="" class="ant-checkbox-input" value=""><span class="ant-checkbox-inner"></span></span><span></span></label><span class="ant-transfer-list-content-item-text"><!----></span></li>
</ul>
</div>
<!---->
</div>
<div class="ant-transfer-operation"><button type="button" class="ant-btn ant-btn-primary ant-btn-sm ant-btn-icon-only"><span role="img" aria-label="right" class="anticon anticon-right"><svg viewBox="64 64 896 896" focusable="false" data-icon="right" width="1em" height="1em" fill="currentColor" aria-hidden="true"><path d="M765.7 486.8L314.9 134.7A7.97 7.97 0 00302 141v77.3c0 4.9 2.3 9.6 6.1 12.6l360 281.1-360 281.1c-3.9 3-6.1 7.7-6.1 12.6V883c0 6.7 7.7 10.4 12.9 6.3l450.8-352.1a31.96 31.96 0 000-50.4z"></path></svg></span></button><button disabled="disabled" type="button" class="ant-btn ant-btn-primary ant-btn-sm ant-btn-icon-only"><span role="img" aria-label="left" class="anticon anticon-left"><svg viewBox="64 64 896 896" focusable="false" data-icon="left" width="1em" height="1em" fill="currentColor" aria-hidden="true"><path d="M724 218.3V141c0-6.7-7.7-10.4-12.9-6.3L260.3 486.8a31.86 31.86 0 000 50.3l450.8 352.1c5.3 4.1 12.9.4 12.9-6.3v-77.3c0-4.9-2.3-9.6-6.1-12.6l-360-281 360-281.1c3.8-3 6.1-7.7 6.1-12.6z"></path></svg></span></button></div>
<div class="ant-transfer-operation"><button class="ant-btn ant-btn-primary ant-btn-sm ant-btn-icon-only" type="button"><span role="img" aria-label="right" class="anticon anticon-right"><svg class="" data-icon="right" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896" focusable="false"><path d="M765.7 486.8L314.9 134.7A7.97 7.97 0 00302 141v77.3c0 4.9 2.3 9.6 6.1 12.6l360 281.1-360 281.1c-3.9 3-6.1 7.7-6.1 12.6V883c0 6.7 7.7 10.4 12.9 6.3l450.8-352.1a31.96 31.96 0 000-50.4z"></path></svg></span></button><button disabled="" class="ant-btn ant-btn-primary ant-btn-sm ant-btn-icon-only" type="button"><span role="img" aria-label="left" class="anticon anticon-left"><svg class="" data-icon="left" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896" focusable="false"><path d="M724 218.3V141c0-6.7-7.7-10.4-12.9-6.3L260.3 486.8a31.86 31.86 0 000 50.3l450.8 352.1c5.3 4.1 12.9.4 12.9-6.3v-77.3c0-4.9-2.3-9.6-6.1-12.6l-360-281 360-281.1c3.8-3 6.1-7.7 6.1-12.6z"></path></svg></span></button></div>
<div class="ant-transfer-list">
<div class="ant-transfer-list-header"><label class="ant-checkbox-wrapper"><span class="ant-checkbox"><input type="checkbox" class="ant-checkbox-input"><span class="ant-checkbox-inner"></span></span></label><span class="ant-transfer-list-header-selected"><span>1 item</span><span class="ant-transfer-list-header-title"></span></span></div>
<div class="ant-transfer-list-header"><label class="ant-checkbox-wrapper"><span class="ant-checkbox"><input type="checkbox" class="ant-checkbox-input" value=""><span class="ant-checkbox-inner"></span></span><span></span></label><span class="ant-transfer-list-header-selected"><span>1 item</span><span class="ant-transfer-list-header-title"></span></span></div>
<div class="ant-transfer-list-body">
<!---->
<ul class="ant-transfer-list-content">
<li class="ant-transfer-list-content-item"><label class="ant-checkbox-wrapper"><span class="ant-checkbox"><input type="checkbox" class="ant-checkbox-input"><span class="ant-checkbox-inner"></span></span></label><span class="ant-transfer-list-content-item-text"></span></li>
<li class="ant-transfer-list-content-item"><label class="ant-checkbox-wrapper"><span class="ant-checkbox"><input type="checkbox" class="ant-checkbox-input" value=""><span class="ant-checkbox-inner"></span></span><span></span></label><span class="ant-transfer-list-content-item-text"><!----></span></li>
</ul>
</div>
<!---->
</div>
</div>
`;

View File

@ -1,7 +1,7 @@
import { mount } from '@vue/test-utils';
import { renderToString } from '@vue/server-test-utils';
import Transfer from '..';
import * as Vue from 'vue';
import { sleep } from '../../../tests/utils';
import { asyncExpect } from '@/tests/utils';
import mountTest from '../../../tests/shared/mountTest';
@ -93,24 +93,18 @@ describe('Transfer', () => {
const props = {
props: listCommonProps,
};
const wrapper = renderToString(Transfer, props);
expect(wrapper).toMatchSnapshot();
const wrapper = mount(Transfer, props);
expect(wrapper.html()).toMatchSnapshot();
});
it('should move selected keys to corresponding list', done => {
const handleChange = jest.fn();
const wrapper = mount(Transfer, {
props: listCommonProps,
listeners: {
change: handleChange,
},
props: { ...listCommonProps, onChange: handleChange },
sync: false,
});
Vue.nextTick(() => {
wrapper
.findAll('.ant-btn')
.at(0)
.trigger('click'); // move selected keys to right list
wrapper.findAll('.ant-btn')[0].trigger('click'); // move selected keys to right list
expect(handleChange).toHaveBeenCalledWith(['a', 'b'], 'right', ['a']);
done();
});
@ -118,83 +112,48 @@ describe('Transfer', () => {
it('should move selected keys expect disabled to corresponding list', done => {
const handleChange = jest.fn();
const wrapper = mount(Transfer, {
props: listDisabledProps,
listeners: {
change: handleChange,
},
props: { ...listDisabledProps, onChange: handleChange },
sync: false,
});
Vue.nextTick(() => {
wrapper
.findAll('.ant-btn')
.at(0)
.trigger('click');
wrapper.findAll('.ant-btn')[0].trigger('click');
expect(handleChange).toHaveBeenCalledWith(['b'], 'right', ['b']);
done();
});
});
it('should uncheck checkbox when click on checked item', done => {
it('should uncheck checkbox when click on checked item', async () => {
const handleSelectChange = jest.fn();
const wrapper = mount(Transfer, {
props: listCommonProps,
listeners: {
selectChange: handleSelectChange,
},
props: { ...listCommonProps, onSelectChange: handleSelectChange },
sync: false,
});
Vue.nextTick(() => {
wrapper
.findAll('.ant-transfer-list-content-item')
.filter(n => {
return n.vnode.data.key === 'a';
})
.trigger('click');
expect(handleSelectChange).toHaveBeenLastCalledWith([], []);
done();
});
await sleep();
wrapper.findAll('.ant-transfer-list-content-item')[0].trigger('click');
expect(handleSelectChange).toHaveBeenLastCalledWith([], []);
});
it('should check checkbox when click on unchecked item', done => {
fit('should check checkbox when click on unchecked item', async () => {
const handleSelectChange = jest.fn();
const wrapper = mount(Transfer, {
props: listCommonProps,
listeners: {
selectChange: handleSelectChange,
},
props: { ...listCommonProps, onSelectChange: handleSelectChange },
sync: false,
});
Vue.nextTick(() => {
wrapper
.findAll('.ant-transfer-list-content-item')
.filter(n => {
return n.vnode.data.key === 'b';
})
.trigger('click');
expect(handleSelectChange).toHaveBeenLastCalledWith(['a'], ['b']);
done();
});
await sleep();
wrapper.findAll('.ant-transfer-list-content-item')[2].trigger('click');
await sleep();
expect(handleSelectChange).toHaveBeenLastCalledWith(['a'], ['b']);
});
it('should not check checkbox when click on disabled item', done => {
it('should not check checkbox when click on disabled item', async () => {
const handleSelectChange = jest.fn();
const wrapper = mount(Transfer, {
props: listCommonProps,
listeners: {
selectChange: handleSelectChange,
},
props: { ...listCommonProps, onSelectChange: handleSelectChange },
sync: false,
});
Vue.nextTick(() => {
wrapper
.findAll('.ant-transfer-list-content-item')
.filter(n => {
return n.vnode.data.key === 'c';
})
.trigger('click');
expect(handleSelectChange).not.toHaveBeenCalled();
done();
});
await sleep();
wrapper.findAll('.ant-transfer-list-content-item')[1].trigger('click');
expect(handleSelectChange).not.toHaveBeenCalled();
});
it('should check all item when click on check all', done => {
@ -250,14 +209,13 @@ describe('Transfer', () => {
sync: false,
});
Vue.nextTick(() => {
const input = wrapper.findAll('.ant-transfer-list-body-search-wrapper input').at(0);
const input = wrapper.findAll('.ant-transfer-list-body-search-wrapper input')[0];
input.element.value = 'a';
input.trigger('input');
Vue.nextTick(() => {
expect(
wrapper
.findAll('.ant-transfer-list-content')
.at(0)
.findAll('.ant-transfer-list-content')[0]
.find('.ant-transfer-list-content-item')
.findAll('input[type="checkbox"]'),
).toHaveLength(1);
@ -279,16 +237,14 @@ describe('Transfer', () => {
sync: false,
});
Vue.nextTick(() => {
const input = wrapper.findAll('.ant-transfer-list-body-search-wrapper input').at(0);
const input = wrapper.findAll('.ant-transfer-list-body-search-wrapper input')[0];
input.element.value = 'content2';
input.trigger('input');
Vue.nextTick(() => {
expect(
wrapper
.findAll('.ant-transfer-list')
.at(0)
.findAll('.ant-transfer-list-header-selected > span')
.at(0)
.findAll('.ant-transfer-list')[0]
.findAll('.ant-transfer-list-header-selected > span')[0]
.text()
.trim(),
).toEqual('1 items');
@ -314,13 +270,12 @@ describe('Transfer', () => {
sync: false,
});
Vue.nextTick(() => {
const input = wrapper.findAll('.ant-transfer-list-body-search-wrapper input').at(0);
const input = wrapper.findAll('.ant-transfer-list-body-search-wrapper input')[0];
input.element.value = 'content2';
input.trigger('input');
Vue.nextTick(() => {
wrapper
.findAll('.ant-transfer-list')
.at(0)
.findAll('.ant-transfer-list')[0]
.findAll('.ant-transfer-list-header input[type="checkbox"]')
.filter(n => {
return !n.vnode.data.domProps.checked;
@ -355,23 +310,19 @@ describe('Transfer', () => {
sync: false,
});
Vue.nextTick(() => {
const input = wrapper.findAll('.ant-transfer-list-body-search-wrapper input').at(0);
const input = wrapper.findAll('.ant-transfer-list-body-search-wrapper input')[0];
input.element.value = 'content2';
input.trigger('input');
Vue.nextTick(() => {
wrapper
.findAll('.ant-transfer-list')
.at(0)
.findAll('.ant-transfer-list')[0]
.findAll('.ant-transfer-list-header input[type="checkbox"]')
.filter(n => {
return !n.vnode.data.domProps.checked;
})
.trigger('change');
Vue.nextTick(() => {
wrapper
.findAll('.ant-btn')
.at(0)
.trigger('click');
wrapper.findAll('.ant-btn')[0].trigger('click');
expect(handleChange).toHaveBeenCalledWith(['1', '3', '4'], 'right', ['1']);
done();
});
@ -404,20 +355,18 @@ describe('Transfer', () => {
.trigger('click');
expect(handleSelectChange).toHaveBeenLastCalledWith(['b'], []);
const input = wrapper.findAll('.ant-transfer-list-body-search-wrapper input').at(0);
const input = wrapper.findAll('.ant-transfer-list-body-search-wrapper input')[0];
input.element.value = 'a';
input.trigger('input');
Vue.nextTick(() => {
wrapper
.findAll('.ant-transfer-list')
.at(0)
.findAll('.ant-transfer-list')[0]
.findAll('.ant-transfer-list-header input[type="checkbox"]')
.trigger('change');
Vue.nextTick(() => {
expect(handleSelectChange).toHaveBeenLastCalledWith(['b', 'a'], []);
wrapper
.findAll('.ant-transfer-list')
.at(0)
.findAll('.ant-transfer-list')[0]
.findAll('.ant-transfer-list-header input[type="checkbox"]')
.trigger('change');
expect(handleSelectChange).toHaveBeenLastCalledWith(['b'], []);
@ -453,8 +402,8 @@ describe('Transfer', () => {
render: item => item.title,
},
};
const wrapper = renderToString(Transfer, props);
expect(wrapper).toMatchSnapshot();
const wrapper = mount(Transfer, props);
expect(wrapper.html()).toMatchSnapshot();
});
it('should add custom styles when their props are provided', async () => {
const style = {
@ -485,9 +434,9 @@ describe('Transfer', () => {
await asyncExpect(() => {
const wrapper = component.find('.ant-transfer');
const list = component.findAll('.ant-transfer-list');
const listSource = list.at(0);
const listSource = list[0];
const listTarget = list.at(list.length - 1);
const operation = component.findAll('.ant-transfer-operation').at(0);
const operation = component.findAll('.ant-transfer-operation')[0];
expect(wrapper.element.style).toHaveProperty('backgroundColor', 'red');
expect(listSource.element.style).toHaveProperty('backgroundColor', 'blue');
expect(listTarget.element.style).toHaveProperty('backgroundColor', 'blue');

View File

@ -38,6 +38,11 @@ export const TransferProps = {
lazy: PropTypes.oneOfType([PropTypes.object, PropTypes.bool]),
showSelectAll: PropTypes.bool,
children: PropTypes.any,
onChange: PropTypes.func,
onSelectChange: PropTypes.func,
onSearchChange: PropTypes.func,
onSearch: PropTypes.func,
onScroll: PropTypes.func,
};
export const TransferLocale = {
@ -378,7 +383,7 @@ const Transfer = {
const locale = this.getLocale(transferLocale, renderEmpty);
const { sourceSelectedKeys, targetSelectedKeys, $slots } = this;
const { body, footer } = $slots;
const renderItem = props.render;
const renderItem = props.render || this.$slots.render;
const { leftDataSource, rightDataSource } = this.separateDataSource();
const leftActive = targetSelectedKeys.length > 0;
const rightActive = sourceSelectedKeys.length > 0;

View File

@ -48,6 +48,9 @@ export const TransferListProps = {
disabled: PropTypes.bool,
direction: PropTypes.string,
showSelectAll: PropTypes.bool,
onItemSelect: PropTypes.func,
onItemSelectAll: PropTypes.func,
onScroll: PropTypes.func,
};
function renderListNode(renderList, props) {

View File

@ -19,12 +19,22 @@ const Operation = (_, { attrs }) => {
return (
<div class={className} style={style}>
<Button type="primary" size="small" disabled={disabled || !rightActive} onClick={moveToRight}>
<RightOutlined slot="icon" />
<Button
type="primary"
size="small"
disabled={disabled || !rightActive}
onClick={moveToRight}
icon={<RightOutlined />}
>
{rightArrowText}
</Button>
<Button type="primary" size="small" disabled={disabled || !leftActive} onClick={moveToLeft}>
<LeftOutlined slot="icon" />
<Button
type="primary"
size="small"
disabled={disabled || !leftActive}
onClick={moveToLeft}
icon={<LeftOutlined />}
>
{leftArrowText}
</Button>
</div>

View File

@ -14,6 +14,9 @@ const ListBody = {
lazy: PropTypes.oneOfType([PropTypes.bool, PropTypes.object]),
selectedKeys: PropTypes.array,
disabled: PropTypes.bool,
onItemSelect: PropTypes.func,
onItemSelectAll: PropTypes.func,
onScroll: PropTypes.func,
},
data() {
return {
@ -53,12 +56,12 @@ const ListBody = {
raf.cancel(this.lazyId);
},
methods: {
onItemSelect(item) {
handleItemSelect(item) {
const { selectedKeys } = this.$props;
const checked = selectedKeys.indexOf(item.key) >= 0;
this.$emit('itemSelect', item.key, !checked);
},
onScroll(e) {
handleScroll(e) {
this.$emit('scroll', e);
},
},
@ -85,7 +88,7 @@ const ListBody = {
renderedEl={renderedEl}
checked={checked}
prefixCls={prefixCls}
onClick={this.onItemSelect}
onClick={this.handleItemSelect}
/>
);
});
@ -93,7 +96,7 @@ const ListBody = {
mounted ? `${prefixCls}-content-item-highlight` : '',
{
tag: 'ul',
onScroll: this.onScroll,
onScroll: this.handleScroll,
onLeave: noop,
},
);

View File

@ -10,6 +10,7 @@ export const TransferSearchProps = {
value: PropTypes.any,
handleClear: PropTypes.func,
disabled: PropTypes.bool,
onChange: PropTypes.func,
};
export default {

View File

@ -4,7 +4,7 @@
</div>
</template>
<script>
import demo from '../antdv-demo/docs/form/demo/validation';
import demo from '../antdv-demo/docs/transfer/demo/basic';
export default {
components: {