diff --git a/packages/amis-ui/src/components/Input.tsx b/packages/amis-ui/src/components/Input.tsx index a353ec326..54482d4fc 100644 --- a/packages/amis-ui/src/components/Input.tsx +++ b/packages/amis-ui/src/components/Input.tsx @@ -31,6 +31,7 @@ class InputInner extends React.Component { @autobind handleComposition(e: React.CompositionEvent) { this.isOnComposition = e.type !== 'compositionend'; + if (!this.isOnComposition) { this.handleChange(e as any); } @@ -47,6 +48,17 @@ class InputInner extends React.Component { }); } + @autobind + handleKeyDown(e: React.KeyboardEvent) { + const {onKeyDown} = this.props; + + if (this.isOnComposition) { + return; + } + + onKeyDown?.(e); + } + render() { const {forwardedRef, ...rest} = this.props; @@ -57,6 +69,7 @@ class InputInner extends React.Component { value={this.state.value} ref={forwardedRef} onChange={this.handleChange} + onKeyDown={this.handleKeyDown} onCompositionStart={this.handleComposition} onCompositionUpdate={this.handleComposition} onCompositionEnd={this.handleComposition} diff --git a/packages/amis-ui/src/components/SearchBox.tsx b/packages/amis-ui/src/components/SearchBox.tsx index 856a7f967..24299fc4a 100644 --- a/packages/amis-ui/src/components/SearchBox.tsx +++ b/packages/amis-ui/src/components/SearchBox.tsx @@ -8,6 +8,7 @@ import {uncontrollable} from 'amis-core'; import {autobind, isMobile} from 'amis-core'; import {LocaleProps, localeable} from 'amis-core'; import chain from 'lodash/chain'; +import Input from './Input'; export interface HistoryRecord { /** 历史记录值 */ @@ -306,17 +307,17 @@ export class SearchBox extends React.Component { )} style={style} > - {!mini && clearable && inputValue && !disabled ? ( diff --git a/packages/amis/__tests__/renderers/SearchBox.test.tsx b/packages/amis/__tests__/renderers/SearchBox.test.tsx index 0e2bb9d64..50c8bf42f 100644 --- a/packages/amis/__tests__/renderers/SearchBox.test.tsx +++ b/packages/amis/__tests__/renderers/SearchBox.test.tsx @@ -6,10 +6,11 @@ * 3. 可清除 clearable * 4. mini 模式 * 5. 立即搜索 searchImediately、样式 className + * 6. Composition触发 */ import React from 'react'; -import {fireEvent, render} from '@testing-library/react'; +import {fireEvent, render, screen} from '@testing-library/react'; import '../../src'; import {render as amisRender} from '../../src'; import {makeEnv, wait} from '../helper'; @@ -36,7 +37,7 @@ test('Renderer:Searchbox', async () => { ) ); - await wait(200); + await wait(500); expect(fetcher).toHaveBeenCalledTimes(1); expect(fetcher.mock.calls[0][0].query).toEqual({ @@ -212,3 +213,34 @@ test('Renderer:Searchbox with searchImediately & className', async () => { keywords: 'aabb' }); }); + +test('6. Renderer: Searchbox is not supposed to be triggered with composition input', async () => { + const onQuery = jest.fn(); + const {container} = render(amisRender({ + type: "search-box", + name: "keywords", + }, { + onQuery + })) + + const inputEl = container.querySelector('.cxd-SearchBox input')!; + expect(inputEl).toBeInTheDocument(); + + /** 第一次输入 Enter 后,文本填入 */ + + fireEvent.compositionStart(inputEl); + fireEvent.keyDown(inputEl, { key: 'Enter', keyCode: 13 }); + await wait(200); + expect(onQuery).not.toHaveBeenCalled(); + + /** 退出输入法,触发搜索 */ + fireEvent.compositionEnd(inputEl); + fireEvent.change(inputEl, {target: {value: 'test'}}); + fireEvent.keyDown(inputEl, { key: 'Enter', keyCode: 13 }); + await wait(200); + + expect(onQuery).toHaveBeenCalledTimes(1); + expect(onQuery.mock.calls[0][0]).toEqual({ + keywords: 'test' + }); +}) diff --git a/packages/amis/__tests__/renderers/__snapshots__/SearchBox.test.tsx.snap b/packages/amis/__tests__/renderers/__snapshots__/SearchBox.test.tsx.snap index f05ed0904..cb5873c66 100644 --- a/packages/amis/__tests__/renderers/__snapshots__/SearchBox.test.tsx.snap +++ b/packages/amis/__tests__/renderers/__snapshots__/SearchBox.test.tsx.snap @@ -22,6 +22,7 @@ exports[`Renderer:Searchbox 1`] = ` autocomplete="off" name="keywords" placeholder="请输入" + type="text" value="searchkey" />