From 41ee8ea046f1413c6c5e67bbb5d58579e3d14ec8 Mon Sep 17 00:00:00 2001 From: tangjinzhou <415800467@qq.com> Date: Mon, 7 Jan 2019 20:58:18 +0800 Subject: [PATCH] feat: transfer change `searchChange` to `search` --- .../__tests__/__snapshots__/demo.test.js.snap | 10 +- .../__snapshots__/index.test.js.snap | 16 +--- .../__tests__/__snapshots__/list.test.js.snap | 4 +- .../__snapshots__/search.test.js.snap | 3 +- components/transfer/__tests__/index.test.js | 10 +- components/transfer/__tests__/search.test.js | 91 +++++++++++++++++++ components/transfer/demo/basic.md | 8 +- components/transfer/demo/index.vue | 26 ++++-- components/transfer/demo/search.md | 4 + components/transfer/index.en-US.md | 4 +- components/transfer/index.jsx | 11 ++- components/transfer/index.zh-CN.md | 4 +- components/transfer/list.jsx | 30 ++---- components/transfer/search.jsx | 11 ++- 14 files changed, 156 insertions(+), 76 deletions(-) diff --git a/components/transfer/__tests__/__snapshots__/demo.test.js.snap b/components/transfer/__tests__/__snapshots__/demo.test.js.snap index 31106cf8b..413ff2593 100644 --- a/components/transfer/__tests__/__snapshots__/demo.test.js.snap +++ b/components/transfer/__tests__/__snapshots__/demo.test.js.snap @@ -30,9 +30,6 @@ exports[`renders ./components/transfer/demo/advanced.md correctly 1`] = `
-
- 没数据 -
@@ -79,7 +76,6 @@ exports[`renders ./components/transfer/demo/basic.md correctly 1`] = `
-
Not Found
- + `; @@ -132,7 +127,6 @@ exports[`renders ./components/transfer/demo/custom-item.md correctly 1`] = `
-
Not Found
1 item
-
  • -
    Not Found
    -
    +
  • `; @@ -28,9 +24,7 @@ exports[`Transfer should show sorted targetkey 1`] = `
    1 item
    -
  • a
  • -
    Not Found
    -
    +
  • a
  • `; diff --git a/components/transfer/__tests__/__snapshots__/list.test.js.snap b/components/transfer/__tests__/__snapshots__/list.test.js.snap index bd3aac36d..4f5da4fa6 100644 --- a/components/transfer/__tests__/__snapshots__/list.test.js.snap +++ b/components/transfer/__tests__/__snapshots__/list.test.js.snap @@ -6,8 +6,6 @@ exports[`List should render correctly 1`] = `
  • -
    -
    Not Found
    -
    + `; diff --git a/components/transfer/__tests__/__snapshots__/search.test.js.snap b/components/transfer/__tests__/__snapshots__/search.test.js.snap index 8a5504fe9..345f13b20 100644 --- a/components/transfer/__tests__/__snapshots__/search.test.js.snap +++ b/components/transfer/__tests__/__snapshots__/search.test.js.snap @@ -4,7 +4,6 @@ exports[`Search should show cross icon when input value exists 1`] = ` `; diff --git a/components/transfer/__tests__/index.test.js b/components/transfer/__tests__/index.test.js index 51b483d47..5ad9ebf3a 100644 --- a/components/transfer/__tests__/index.test.js +++ b/components/transfer/__tests__/index.test.js @@ -222,7 +222,7 @@ describe('Transfer', () => { Vue.nextTick(() => { const input = wrapper.findAll('.ant-transfer-list-body-search-wrapper input').at(0) input.element.value = 'a' - input.trigger('change') + input.trigger('input') Vue.nextTick(() => { expect(wrapper.findAll('.ant-transfer-list-content') .at(0) @@ -248,7 +248,7 @@ describe('Transfer', () => { Vue.nextTick(() => { const input = wrapper.findAll('.ant-transfer-list-body-search-wrapper input').at(0) input.element.value = 'content2' - input.trigger('change') + input.trigger('input') Vue.nextTick(() => { expect(wrapper.findAll('.ant-transfer-list') .at(0) @@ -280,7 +280,7 @@ describe('Transfer', () => { Vue.nextTick(() => { const input = wrapper.findAll('.ant-transfer-list-body-search-wrapper input').at(0) input.element.value = 'content2' - input.trigger('change') + input.trigger('input') Vue.nextTick(() => { wrapper.findAll('.ant-transfer-list') .at(0) @@ -318,7 +318,7 @@ describe('Transfer', () => { Vue.nextTick(() => { const input = wrapper.findAll('.ant-transfer-list-body-search-wrapper input').at(0) input.element.value = 'content2' - input.trigger('change') + input.trigger('input') Vue.nextTick(() => { wrapper.findAll('.ant-transfer-list') .at(0) @@ -358,7 +358,7 @@ describe('Transfer', () => { const input = wrapper.findAll('.ant-transfer-list-body-search-wrapper input').at(0) input.element.value = 'a' - input.trigger('change') + input.trigger('input') Vue.nextTick(() => { wrapper.findAll('.ant-transfer-list') .at(0) diff --git a/components/transfer/__tests__/search.test.js b/components/transfer/__tests__/search.test.js index bcbed8c23..3e0b81d7b 100644 --- a/components/transfer/__tests__/search.test.js +++ b/components/transfer/__tests__/search.test.js @@ -1,7 +1,19 @@ import { mount } from '@vue/test-utils' +import { asyncExpect } from '@/tests/utils' import Search from '../search' +import Transfer from '../index' describe('Search', () => { + const errorSpy = jest.spyOn(console, 'error').mockImplementation(() => {}) + + afterEach(() => { + errorSpy.mockReset() + }) + + afterAll(() => { + errorSpy.mockRestore() + }) + it('should show cross icon when input value exists', () => { const props = { propsData: { @@ -16,4 +28,83 @@ describe('Search', () => { expect(wrapper.html()).toMatchSnapshot() }) + + it('onSearch', async () => { + const dataSource = [ + { + key: 'a', + title: 'a', + description: 'a', + }, + { + key: 'b', + title: 'b', + description: 'b', + }, + { + key: 'c', + title: 'c', + description: 'c', + }, + ] + + const onSearch = jest.fn() + const wrapper = mount({ + render () { + return item.title} + onSearch={onSearch} + showSearch + /> + }, + }, { + sync: false, + }) + await asyncExpect(() => { + const input = wrapper + .findAll('.ant-input') + .at(0) + input.element.value = 'a' + input.trigger('input') + }) + + await asyncExpect(() => { + expect(onSearch).toBeCalledWith('left', 'a') + }) + + onSearch.mockReset() + + wrapper + .findAll('.ant-transfer-list-search-action') + .at(0) + .trigger('click') + expect(onSearch).toBeCalledWith('left', '') + }) + + it('legacy onSearchChange', () => { + const onSearchChange = jest.fn() + + const wrapper = mount({ + render () { + return item.title} onSearchChange={onSearchChange} showSearch /> + }, + }, { + sync: false, + }) + + const input = wrapper + .findAll('.ant-input') + .at(0) + input.element.value = 'a' + input.trigger('input') + + expect(errorSpy.mock.calls[0][0]).toMatch( + 'Warning: `searchChange` in Transfer is deprecated. Please use `search` instead.', + ) + expect(onSearchChange.mock.calls[0][0]).toEqual('left') + expect(onSearchChange.mock.calls[0][1].target.value).toEqual('a') + }) }) diff --git a/components/transfer/demo/basic.md b/components/transfer/demo/basic.md index 61d371988..b1f8bfd69 100644 --- a/components/transfer/demo/basic.md +++ b/components/transfer/demo/basic.md @@ -22,7 +22,13 @@ The most basic usage of `Transfer` involves providing the source data and target :render="item=>item.title" :disabled="disabled" /> - + diff --git a/components/transfer/index.en-US.md b/components/transfer/index.en-US.md index 36f0160e1..8be0fa733 100644 --- a/components/transfer/index.en-US.md +++ b/components/transfer/index.en-US.md @@ -9,7 +9,7 @@ | lazy | property of vc-lazy-load for lazy rendering items. Turn off it by set to `false`. | object\|boolean | `{ height: 32, offset: 32 }` | | listStyle | A custom CSS style used for rendering the transfer columns. | object | | | locale | i18n text including filter, empty text, item unit, etc | object | `{ itemUnit: 'item', itemsUnit: 'items', notFoundContent: 'The list is empty', searchPlaceholder: 'Search here' }` | -| operations | A set of operations that are sorted from bottom to top. | string\[] | ['>', '<'] | +| operations | A set of operations that are sorted from top to bottom. | string\[] | ['>', '<'] | | render | The function to generate the item shown on a column. Based on an record (element of the dataSource array), this function should return a element which is generated from that record. Also, it can return a plain object with `value` and `label`, `label` is a element and `value` is for title | Function(record) | | | selectedKeys | A set of keys of selected items. | string\[] | \[] | | showSearch | If included, a search box is shown on each column. | boolean | false | @@ -21,7 +21,7 @@ | --- | --- | --- | | change | A callback function that is executed when the transfer between columns is complete. | (targetKeys, direction, moveKeys): void | | | scroll | A callback function which is executed when scroll options list | (direction, event): void | | -| searchChange | A callback function which is executed when search field are changed | (direction: 'left'\|'right', event: Event): void | - | +| search | A callback function which is executed when search field are changed | (direction: 'left'\|'right', value: string): void | - | | selectChange | A callback function which is executed when selected items are changed. | (sourceSelectedKeys, targetSelectedKeys): void | | ## Warning diff --git a/components/transfer/index.jsx b/components/transfer/index.jsx index c38159189..9953522b6 100644 --- a/components/transfer/index.jsx +++ b/components/transfer/index.jsx @@ -6,6 +6,7 @@ import List from './list' import Operation from './operation' import LocaleReceiver from '../locale-provider/LocaleReceiver' import defaultLocale from '../locale-provider/default' +import warning from '../_util/warning' export const TransferDirection = 'left' | 'right' @@ -225,11 +226,16 @@ const Transfer = { }, handleFilter (direction, e) { + const value = e.target.value this.setState({ // add filter - [`${direction}Filter`]: e.target.value, + [`${direction}Filter`]: value, }) - this.$emit('searchChange', direction, e) + if (this.$listeners.searchChange) { + warning(false, '`searchChange` in Transfer is deprecated. Please use `search` instead.') + this.$emit('searchChange', direction, e) + } + this.$emit('search', direction, value) }, handleLeftFilter (e) { @@ -243,6 +249,7 @@ const Transfer = { this.setState({ [`${direction}Filter`]: '', }) + this.$emit('search', direction, '') }, handleLeftClear () { diff --git a/components/transfer/index.zh-CN.md b/components/transfer/index.zh-CN.md index 4fcc227fc..97699ac2b 100644 --- a/components/transfer/index.zh-CN.md +++ b/components/transfer/index.zh-CN.md @@ -9,7 +9,7 @@ | lazy | Transfer 使用了 [vc-lazy-load]优化性能,这里可以设置相关参数。设为 `false` 可以关闭懒加载。 | object\|boolean | `{ height: 32, offset: 32 }` | | listStyle | 两个穿梭框的自定义样式 | object | | | locale | 各种语言 | object | `{ itemUnit: '项', itemsUnit: '项', notFoundContent: '列表为空', searchPlaceholder: '请输入搜索内容' }` | -| operations | 操作文案集合,顺序从下至上 | string\[] | ['>', '<'] | +| operations | 操作文案集合,顺序从上至下 | string\[] | ['>', '<'] | | render | 每行数据渲染函数,该函数的入参为 `dataSource` 中的项,返回值为 element。或者返回一个普通对象,其中 `label` 字段为 element,`value` 字段为 title | Function(record) | | | selectedKeys | 设置哪些项应该被选中 | string\[] | \[] | | showSearch | 是否显示搜索框 | boolean | false | @@ -21,7 +21,7 @@ | --- | --- | --- | | change | 选项在两栏之间转移时的回调函数 | (targetKeys, direction, moveKeys): void | | | scroll | 选项列表滚动时的回调函数 | (direction, event): void | | -| searchChange | 搜索框内容时改变时的回调函数 | (direction: 'left'\|'right', event: Event): void | - | +| search | 搜索框内容时改变时的回调函数 | (direction: 'left'\|'right', value: string): void | - | | selectChange | 选中项发生改变时的回调函数 | (sourceSelectedKeys, targetSelectedKeys): void | | ## 注意 diff --git a/components/transfer/list.jsx b/components/transfer/list.jsx index 5f7adc89c..3256206ba 100644 --- a/components/transfer/list.jsx +++ b/components/transfer/list.jsx @@ -9,10 +9,6 @@ import Item from './item' import triggerEvent from '../_util/triggerEvent' import addEventListener from '../_util/Dom/addEventListener' -function isIEorEDGE () { - return document.documentMode || /Edge/.test(navigator.userAgent) -} - function noop () { } @@ -87,7 +83,6 @@ export default { beforeDestroy () { clearTimeout(this.timer) clearTimeout(this.triggerScrollTimer) - clearTimeout(this.fixIERepaintTimer) if (this.scrollEvent) { this.scrollEvent.remove() } @@ -135,11 +130,9 @@ export default { triggerEvent(listNode, 'scroll') } }, 0) - this.fixIERepaint() }, _handleClear (e) { this.handleClear(e) - this.fixIERepaint() }, matchFilter (text, item) { const { filter, filterOption } = this.$props @@ -157,20 +150,6 @@ export default { renderedEl: isRenderResultPlain ? renderResult.label : renderResult, } }, - - // Fix IE/Edge repaint - // https://github.com/ant-design/ant-design/issues/9697 - // https://stackoverflow.com/q/27947912/3040605 - fixIERepaint () { - if (!isIEorEDGE()) { - return - } - this.fixIERepaintTimer = window.setTimeout(() => { - if (this.$refs.notFoundNode) { - this.$refs.notFoundNode.className = this.$refs.notFoundNode.className - } - }, 0) - }, filterNull (arr) { return arr.filter((item) => { return item !== null @@ -235,6 +214,7 @@ export default { handleClear={this.handleClear} placeholder={searchPlaceholder} value={filter} + disabled={disabled} /> ) : null @@ -242,6 +222,10 @@ export default { const transitionProps = getTransitionProps(transitionName, { leave: noop, }) + + const searchNotFound = showItems.every(item => item === null) && ( +
    {notFoundContent}
    + ) const listBody = bodyDom || (
    {showItems} -
    - {notFoundContent} -
    + {searchNotFound}
    ) diff --git a/components/transfer/search.jsx b/components/transfer/search.jsx index dca35f726..d09a2b534 100644 --- a/components/transfer/search.jsx +++ b/components/transfer/search.jsx @@ -8,6 +8,7 @@ export const TransferSearchProps = { placeholder: PropTypes.string, value: PropTypes.any, handleClear: PropTypes.func, + disabled: PropTypes.bool, } export default { @@ -21,16 +22,17 @@ export default { }, handleClear2 (e) { e.preventDefault() - if (this.handleClear) { - this.handleClear(e) + const { handleClear, disabled } = this.$props + if (!disabled && handleClear) { + handleClear(e) } }, }, render () { - const { placeholder, value, prefixCls } = getOptionProps(this) + const { placeholder, value, prefixCls, disabled } = getOptionProps(this) const icon = (value && value.length > 0) ? ( - + ) : ( @@ -44,6 +46,7 @@ export default { value={value} ref='input' onChange={this.handleChange} + disabled={disabled} /> {icon}