React - Internet Explorer 11 输入在第一次 onchange 后失去焦点 [英] React - Internet explorer 11 input loses focus after first onchange

查看:32
本文介绍了React - Internet Explorer 11 输入在第一次 onchange 后失去焦点的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我遇到了一个非常奇怪的问题,我无法解决.我目前正在使用 react 16.3 和 Antd 3.11 框架使用 create-react-app,我创建了一个表,在它的标题列中呈现一个附加了 onChange 事件的组件.

当我第一次聚焦输入时,问题就出现了.

我失去了对第一个关键事件的关注,然后当我再次单击该字段时,它会一直保持聚焦,直到我单击其他内容为止.

这是我一直在使用的示例:https://ant.design/components/table/

以及后面的代码.

import {表,输入,按钮,图标,来自'antd';常量数据 = [{键:'1',姓名:'约翰·布朗',年龄:32,地址:'纽约第一湖公园',}, {键:'2',姓名:'乔·布莱克',年龄:42,地址:'伦敦第一湖公园',}, {键:'3',姓名:'吉姆·格林',年龄:32,地址:'悉尼一号湖公园',}, {键:'4',name: 'Jim Red',年龄:32,地址:'伦敦2号湖公园',}];类 App 扩展了 React.Component {状态 = {搜索文本:'',};handleSearch = (selectedKeys, confirm) =>() =>{确认();this.setState({ searchText: selectedKeys[0] });}handleReset = clearFilters =>() =>{清除过滤器();this.setState({ searchText: '' });}使成为() {常量列 = [{title: '姓名',数据索引:'名称',键:'名称',过滤器下拉列表:({setSelectedKeys,selectedKeys,确认,clearFilters,}) =>(<div className="custom-filter-dropdown"><输入ref={ele =>this.searchInput = ele}占位符=搜索名称"值={selectedKeys[0]}onChange={e =>setSelectedKeys(e.target.value ? [e.target.value] : [])}onPressEnter={this.handleSearch(selectedKeys, confirm)}/><Button type="primary" onClick={this.handleSearch(selectedKeys, confirm)}>搜索</Button><Button onClick={this.handleReset(clearFilters)}>Reset</Button>

),过滤器图标:过滤 =><Icon type="smile-o" style={{ 颜色:过滤?'#108ee9' : '#aaa' }}/>,onFilter: (value, record) =>record.name.toLowerCase().includes(value.toLowerCase()),onFilterDropdownVisibleChange: (可见) =>{如果(可见){setTimeout(() => {this.searchInput.focus();});}},渲染:(文本)=>{const { searchText } = this.state;返回搜索文本?(<跨度>{text.split(new RegExp(`(${searchText})`, 'gi')).map((fragment, i) => (fragment.toLowerCase() === searchText.toLowerCase()?<span key={i} className="highlight">{fragment}</span>: fragment//eslint-disable-line))}</span>) : 文本;},}, {title: '年龄',数据索引:'年龄',键:'年龄',}, {title: '地址',数据索引:'地址',键:'地址',过滤器:[{文本:'伦敦',价值:'伦敦',}, {文本:'纽约',价值:'纽约',}],onFilter: (value, record) =>record.address.indexOf(value) === 0,}];return <Table columns={columns} dataSource={data}/>;}}ReactDOM.render(, mountNode);

以及随之而来的css:

.custom-filter-dropdown {填充:8px;边框半径:6px;背景:#fff;box-shadow: 0 1px 6px rgba(0, 0, 0, .2);}.custom-filter-dropdown 输入 {宽度:130px;右边距:8px;}.custom-filter-dropdown 按钮 {右边距:8px;}.强调 {颜色:#f50;}

快速总结一下我理解的内容.

  • 表格重新渲染了 filterDropDown 道具,filterIcon 在每个按键.
  • 表所在的类组件不重新渲染或触发器(componentDidUpdate)
  • 这在 Chrome、FireFox、Edge 中完美运行,示例在antds 网站上的 IE11.但不在我的应用中.
  • 在我自己的组件中渲染的所有 antd 字段和常规字段在任何浏览器中都没有这个问题.
  • 在渲染函数之外渲染输入组件不会工作,因为它不是我的组件重新渲染它是触发它自己的更新事件的表组件
  • 我还尝试将 -ms-user-select: 设置更改为不同的属性,以查看是否有影响的天气.事实上,这只会让事情变得更糟.
  • 我尝试将输入值设置为状态值以使其成为受控组件,但是当 componentDidUpdate 触发并且我以编程方式将 .focus 设置在我的输入上时,它会设置 caretIndex lenght-1 而不是在文本后面.(我手动尝试覆盖 selectionStart 和 SelectionEnd 但没有成功

我有点想不通了,因为我了解到一些其他组件正在窃取我的输入框的焦点,但是即使我使用过,我也无法找到该元素document.activeElement 在我能想到的几乎所有方法和生命周期事件中.所有事件都指向具有焦点的a"输入字段(不确定这是旧的还是新创建的,但我认为是旧的).

我已尽力解释我的情况,我希望世界上有人遇到过类似的问题.

更新:antd 合理地更改了他们的表格组件,因此网页上的示例略有不同,但问题仍然相同.

解决方案

我在 IE11 上有同样的行为.

可以通过在 Input 字段上添加一个额外的 onBlur 来修复它,只需将焦点设置为 currentTarget.

onBlurHandler = (e: React.FocusEvent) =>{e.currentTarget.focus();};

I have come across a very strange issue that I can't wrap my head around. I'm currently working with an create-react-app using react 16.3 and Antd 3.11 framework and I have created a table which inside it's header column renders a component with an onChange event attached.

The issue comes when I focus the input for the first time.

I lose focus on first key event, and afterwards when I click the field again, it remains focused until I click something else.

Here is the example I have been using: https://ant.design/components/table/

and the code that follows.

import {
  Table, Input, Button, Icon,
} from 'antd';

const data = [{
  key: '1',
  name: 'John Brown',
  age: 32,
  address: 'New York No. 1 Lake Park',
}, {
  key: '2',
  name: 'Joe Black',
  age: 42,
  address: 'London No. 1 Lake Park',
}, {
  key: '3',
  name: 'Jim Green',
  age: 32,
  address: 'Sidney No. 1 Lake Park',
}, {
  key: '4',
  name: 'Jim Red',
  age: 32,
  address: 'London No. 2 Lake Park',
}];

class App extends React.Component {
  state = {
    searchText: '',
  };

  handleSearch = (selectedKeys, confirm) => () => {
    confirm();
    this.setState({ searchText: selectedKeys[0] });
  }

  handleReset = clearFilters => () => {
    clearFilters();
    this.setState({ searchText: '' });
  }

  render() {
    const columns = [{
      title: 'Name',
      dataIndex: 'name',
      key: 'name',
      filterDropdown: ({
        setSelectedKeys, selectedKeys, confirm, clearFilters,
      }) => (
        <div className="custom-filter-dropdown">
          <Input
            ref={ele => this.searchInput = ele}
            placeholder="Search name"
            value={selectedKeys[0]}
            onChange={e => setSelectedKeys(e.target.value ? [e.target.value] : [])}
            onPressEnter={this.handleSearch(selectedKeys, confirm)}
          />
          <Button type="primary" onClick={this.handleSearch(selectedKeys, confirm)}>Search</Button>
          <Button onClick={this.handleReset(clearFilters)}>Reset</Button>
        </div>
      ),
      filterIcon: filtered => <Icon type="smile-o" style={{ color: filtered ? '#108ee9' : '#aaa' }} />,
      onFilter: (value, record) => record.name.toLowerCase().includes(value.toLowerCase()),
      onFilterDropdownVisibleChange: (visible) => {
        if (visible) {
          setTimeout(() => {
            this.searchInput.focus();
          });
        }
      },
      render: (text) => {
        const { searchText } = this.state;
        return searchText ? (
          <span>
            {text.split(new RegExp(`(${searchText})`, 'gi')).map((fragment, i) => (
              fragment.toLowerCase() === searchText.toLowerCase()
                ? <span key={i} className="highlight">{fragment}</span> : fragment // eslint-disable-line
            ))}
          </span>
        ) : text;
      },
    }, {
      title: 'Age',
      dataIndex: 'age',
      key: 'age',
    }, {
      title: 'Address',
      dataIndex: 'address',
      key: 'address',
      filters: [{
        text: 'London',
        value: 'London',
      }, {
        text: 'New York',
        value: 'New York',
      }],
      onFilter: (value, record) => record.address.indexOf(value) === 0,
    }];
    return <Table columns={columns} dataSource={data} />;
  }
}

ReactDOM.render(<App />, mountNode);

And the css that follows to that:

.custom-filter-dropdown {
  padding: 8px;
  border-radius: 6px;
  background: #fff;
  box-shadow: 0 1px 6px rgba(0, 0, 0, .2);
}

.custom-filter-dropdown input {
  width: 130px;
  margin-right: 8px;
}

.custom-filter-dropdown button {
  margin-right: 8px;
}

.highlight {
  color: #f50;
}

To quickly sum up things i've come to understand.

  • The table rerenders the filterDropDown prop, filterIcon on every keystroke.
  • The class component where the table is within does not rerender or trigger(componentDidUpdate)
  • This works perfectly in Chrome, FireFox, Edge and the sample works in IE11 on antds website. however not in my app.
  • All antd fields and regular fields which are rendered in my own components does not have this problem in any browser.
  • Rendering the input components outside the render function does not work since it is not my component that rerenders it is the table component that triggers it's own update events
  • I have also tried to change -ms-user-select: settings to different attributes to see weather that had an effect or not. fact was it only made it worse.
  • I've tried to set input value as a state value to make it a controlled component, however when componentDidUpdate triggers and I programtically set .focus on my input it sets caretIndex lenght-1 instead of behind text. (I have manually tried to override selectionStart and SelectionEnd but without success

I'm sort of running out of ideas since what I have come to understand is that some other component is stealing the focus of my input box, however I have not been able to find the element even though I've used document.activeElement in almost every method and lifecycle event I could think of. All events point to the 'a' Input field having focus (not sure if this is the old or new one created, however I think it's the old one).

I have tried my best to explain my scenario and I hope someone out there in the world has come across a similar issue.

UPDATE: antd reasonly changed their table component so the example is a bit different on the webpage, however issue still remains the same.

解决方案

I hade the same behavior on IE11.

Could fix it with an additional onBlur on the Input field, that just set the focus to the currentTarget.

onBlurHandler = (e: React.FocusEvent<HTMLInputElement>) => {
    e.currentTarget.focus();
};

这篇关于React - Internet Explorer 11 输入在第一次 onchange 后失去焦点的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆