【问题标题】:I have a question about the Focus event and the Blur event我对 Focus 事件和 Blur 事件有疑问
【发布时间】:2019-03-07 09:28:17
【问题描述】:

对于这个模棱两可的标题,我深表歉意。很难用一句话来说明问题。

首先,我的代码结构是这样的(使用 JSX)

<Parent>
    <EditableText1 />
    <EditableText2 />
</Parent>

这是我希望它的工作方式:

  • 在默认状态下,ET2(EditableText2)的“显示”为“无”

  • 当 'Parent' 为 'Focus' ET2 的 'display' 值变为 'flex'

  • 当 'Parent' 为 'Blur' 时,ET2 的 'display' 值再次变为 'none'

  • 也就是说,如果选择了 ET1(ET1 可见),则 ET2 变为可见,并且可以在该状态下编辑 ET2。

这是我的尝试:

1)

<Parent 
onFocus={() => { this.setState({ visible: 'flex' }) }} 
onBlur={() => { this.setState({ visible: 'none' }) }>
    <EditableText1 />
    <EditableText2 className={css`
display: ${this.state.visible};
`/>
</Parent>

这里的问题是这样的:

当 ET1 成为“焦点”时,会出现 ET2。但是,如果我尝试选择 ET2,则 ET1 变为“模糊”,因此 ET2 的“显示”变为“无”。所以我不能选择ET2!

2) 所以我尽量防止ET1模糊时冒泡:

<Parent 
onFocus={() => { this.setState({ visible: 'flex' }) }} 
onBlur={() => { this.setState({ visible: 'none' }) }>
    <EditableText1 
onBlur={(e) => { e.stopPropagation() }}
/>
    <EditableText2 className={css`
display: ${this.state.visible};
`/>
</Parent>

这个案例的问题是这样的:

现在可以在 ET1 聚焦后选择 ET2。 但, 如果我从 ET1 模糊到 Parent 之外,则 ET2 的“显示”不会变为“无”。

如果我从 ET2 模糊父级之外,“显示”将变为“无”(我希望它的工作方式)。

我不知道该怎么办了。这似乎是因为我缺乏知识。任何人都可以给我一个方法或给我一个提示吗?

【问题讨论】:

  • 如果你在这个问题的标题中找到合适的句子,如果你能告诉我,我将不胜感激。

标签: javascript html css reactjs dom


【解决方案1】:

这是一个可能的解决方案。它不是最漂亮的,但我工作。主要思想是在状态中存储哪个元素具有焦点。当 ET1 元素上发生模糊事件时,您需要检查 ET2 是否具有焦点。为此,您需要创建一个延迟,因为模糊事件将在焦点事件之前触发。没有这种延迟,状态告诉哪个元素有焦点,还没有更新。

import React from "react";

export default class myClass extends React.Component {
  constructor() {
    super();
    this.beforeBlur = this.beforeBlur.bind(this);
    this.update = this.update.bind(this);
    this.state = {
      whoHasFocus: "none",
      visible: "none"
    };
    this.delay = null;
  }

  beforeBlur(obj) {
    const that = this;
    this.delay = setInterval(() => {
      if (this.state.whoHasFocus !== "ET2") {
        this.update(obj);
      }
      clearInterval(that.delay);
    }, 10);
  }
  update(obj) {
    this.setState(obj);
  }
  render() {
    return (
      <div>
        <input
          type="text"
          onBlur={() => {
            this.beforeBlur({
              visible: "none",
              whoHasFocus: "none"
            });
          }}
          onFocus={() => {
            this.update({
              visible: "flex",
              whoHasFocus: "ET1"
            });
          }}
        />
        <input
          type="text"
          style={{ display: `${this.state.visible}` }}
          onFocus={() => {
            this.update({ whoHasFocus: "ET2" });
          }}
          onBlur={e => {
            this.update({
              visible: "none",
              whoHasFocus: "none"
            })
          }}
        />
      </div>
    )
  }
}

我希望这对你有任何帮助。

【讨论】:

  • 非常感谢。我会试试这个并再次发表评论。
  • 我将此方法应用于我的代码。尽管使用 setInterval 让我感到紧张,但显然它似乎有效。谢谢。
  • @SunghoYahng 我分享您对使用setInterval 的担忧。我几乎可以向你保证,这会在未来再次咬你一口。
【解决方案2】:

我最终决定使用这种方法。

<div class="Parent">
  <input type="text" id="ET1" />
  <br />
  <input type="text" id="ET2" />
</div>

.Parent:focus-within #ET2 {
  display: flex;
}

#ET2 {
  display: none;
}

我在 devpal.io 上提出了一个问题,得到了这个答案并得到了帮助。谢谢你,安迪。

你好! 好的,所以他们的响应有效,但我可能会采用 CSS 方法,使用 :focus-within: https://www.scottohara.me/blog/2017/05/14/focus-within.html 它有非常好的浏览器支持:https://caniuse.com/#feat=css-focus-within 我认为你会得到更多的弹性来接近它。 希望对您有所帮助

【讨论】:

  • 太棒了!我同意,间隔是不可持续的,这个解决方案看起来要简单得多。很好的发现。谢谢!
猜你喜欢
  • 2010-12-11
  • 2012-11-13
  • 2012-05-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-22
  • 2023-03-09
  • 2016-08-18
相关资源
最近更新 更多