【问题标题】:React replace event.target with input用输入反应替换 event.target
【发布时间】:2018-08-16 01:08:24
【问题描述】:

更新 这是一些演示

contentEditable demo - 需要双击 H1 才能编辑

replace with input demo - 采用event.target 样式,但在渲染时使 UI '抽搐'


所以我有一些功能组件,比如说:

component1.js

import React from 'react';
const component1 = props => (
<div>
 <h1>Title</h1>
</div>
);
export { component1 };

它们是可变的。 event.target 可以是任何带有文本的东西,比如段落、标题等等。我试图让用户通过点击它来编辑内联内容,所以我将一个函数editMode 传递给这些功能组件,它将使用编辑信息更新父状态,让我们这样说:

&lt;h1 onClick={event =&gt; {editMode(event, props.name, props.title, 'title')}}&gt;title&lt;/h1&gt;

这将更改父本地状态以获取从 redux 获取值、定义目标等所需的所有信息。对于此示例,props.name 是组件的名称,props.title 是值,@987654333 @ 是 redux 中的对象键。

所以我会在我的 component1.js 中添加一些东西,让它看起来有点像这样:

import React from 'react';
const component1 = props => (
    <div>
        {props.editState === 'true' &&
            <EditLayout
                name={props.name}
                target={props.target}
                value={props.value}
                onChange={event => someFunc(event)}
            />
        }
        <h1>Title</h1>
    </div>
    );
export { component1 };

现在这可以正常工作了,只是它不能扩展。在这种情况下,EditLayout 只会返回具有正确值的输入。我需要它做的是适应被点击的任何内容,获取字体大小、背景、填充、边距、位置。我这样做对吗?我尝试的每一种方式都会遇到巨大的问题:

想法 1 - 将 EditLayout 组件移到功能组件之外

问题:定位

所以我将 EditLayout 移动到包含 component1.jsEditLayout 的父组件。这将允许我从功能组件内部操作它,而不必在任何地方都包含它。然后我会从event.target 获取坐标和其他重要信息,如下所示:

const coords = event.target.getBoundingClientRect();
const offsetX = coords.left;
const offsetY = coords.top;
const childHeight = coords.height;
const childWidth = coords.width;
const childClass = event.target.className;

然后我将包装EditLayout 以返回一个包含输入的容器,并将大小/坐标应用于绝对定位的容器。这将出现输入被随机数量的像素偏移的问题,具体取决于event.target 的大小/位置。

想法 2 - 将相关的计算样式传递给 EditLayout

问题:渲染时抖动,我必须为每个可能的 event.target 添加 EditLayout,并调整其渲染

所以我会像这样抓取所有重要的计算样式:

const computedTarget = window.getComputedStyle(event.target);
const childMargins = computedTarget.marginBottom;
const childPaddings = computedTarget.padding;
const childFontSize = computedTarget.fontSize;
const childTextAlign = computedTarget.textAlign;

并将其传递给component1.js,然后将其传递给component1.js. I'll then condition theevent.target 内的EditLayout 组件,以隐藏它是否正在被这样编辑:

<h1 className={ props.target === 'title' ? 'd-none' : ''}>Title</h1>

并将EditLayout 设置为仅在需要时显示:

{props.target === 'title' && <EditLayout />}

在此示例中,单击 h1 将显示输入,但布局本身在渲染时会出现抽搐。输入将具有与 h1 或 event.target 完全相同的边距和字体大小,但它会显得更大并扩展布局。演示:

想法 3 - 使用有条件的 contentEditable

问题:需要双击才能启用,在 safari 中不起作用,不允许我预先选择值

这是最奇怪的。我认为这很简单,在功能组件渲染中做这样的事情:

&lt;h1 contentEditable={props.target === 'title'} onClick={event =&gt; props.setTarget(event)}&gt;Title&lt;/h1&gt;

但是,我必须双击才能启用它。我不知道为什么,如果每次onClick 被触发时都附加一个控制台日志,我会得到正确的输出,我也会得到正确的目标值。我尝试了很多方法,但它只需要双击。即使尝试在功能组件内部处理这个问题,因为大部分东西都是由父组件处理的,也没有什么区别。

我对示例进行了过度简化,因此可以安全地假设/理解以下内容:

  • 我以正确的方式传递道具,它们不是未定义的
  • 我正在使用引导程序
  • 我正在使用样式化组件,而EditLayout 是样式化组件 它接受道具并将它们转换为 CSS,例如:font-size: ${props => props.fontSize};
  • 这些值应该是正确的,我没有操纵从getComputedStyle()getBoundingClientRect() 返回的任何东西
  • 我热衷于保持我的功能组件正常运行,并且易于 添加。在这种情况下,功能组件是简单的 HTML 结构, 我想让它们尽可能简单

【问题讨论】:

  • 您是否考虑过使用contentEditable 并绑定到输入事件与尝试克隆所有内容?
  • 是的,但是,它没有给我足够的控制权,它只能在双击时起作用(不知道为什么),而且它直接在 safari 中不起作用。所以我认为输入更友好,更容易控制。
  • 关于event.target 的使用。假设我们谈论的是原生 JavaScript 的 event.target。请阅读event.currentTarget 并确保event.target 正是您想要的。一般currentTarget比较安全;因为,它比target 更可预测。 currentTarget 始终指代事件附加到的元素,target 指代发生事件的元素。
  • 所以@Tyler 我没有任何关于 event.target 错误的问题,因为由于传递了很多东西,我永久记录了该过程的每一步,但我会尝试更新到 currentTarget 看看它是否会有所作为。我假设您的目标是修复 contentEditable 方法
  • @PredragBeocanin 实际上它可能与您的问题无关。这只是未来可能出现的错误;因为,target 不能保证每次都引用同一个元素。由于currentTarget 总是指代相同的元素,因此使用起来更容易预测和更安全。

标签: javascript reactjs


【解决方案1】:

因此,contentEditable 需要单击两次而不是单击一次,而不是绑定 onClick 并将其传递以启用 contentEditable,因此有一个简洁的解决方案,只需保持 contentEditable 为真,然后根据需要处理更改。这是一个有效的h1,不需要点击两次即可启用contentEditable,与演示中的不同

<h1
    className="display-4 text-center"
    contentEditable
    suppressContentEditableWarning
    onBlur={event =>  updateValues(event)}
>
    Title 
</h1>

触发器更新的可用方法可以是onBluronInput

【讨论】:

    猜你喜欢
    • 2021-03-06
    • 1970-01-01
    • 1970-01-01
    • 2019-01-16
    • 1970-01-01
    • 2012-06-19
    • 2022-01-21
    • 2020-10-13
    • 2018-01-11
    相关资源
    最近更新 更多