手动调用`createElement`是不好的形式?

时间:2015-11-02 00:37:45

标签: javascript reactjs

我在我的React项目中到处使用JSX,因为我当然是。 但是有一些情况下使用createElement特别有帮助。

这是一个这样的例子,它代表了我的典型用例。 我有一个合理大小的字符串,我希望在<pre>标记中显示,但我希望\r0x0D)字符的所有实例都显示为{{1} } 使用不同的颜色。 我可以很容易地实现如下

<CR>

确实产生了

the result of the above code, showing both a correctly processed carriage return and the literal text "<CR>"; the latter is not colored

我在这里看到的替代方案是为字符串中的每个字符生成单独的const splitOnCR = stdin.split("\r"); const joinerStyle = { color: "#337ab7", // Bootstrap primary color } const joiner = <tt style={joinerStyle}>{"<CR>"}</tt>; let parts = new Array(splitOnCR.length * 2 - 1); for (let i = 0; i < parts.length; i++) { if (i % 2 === 0) { parts[i] = splitOnCR[i / 2]; } else { parts[i] = joiner; } } const style = { fontFamily: "monospace", // override Menlo or whatever }; return React.createElement( "pre", {style}, ...parts, <span>&nbsp;</span>, // show final newlines, if any ); <tt>或其他内容,然后将它们全部呈现在数组中。 我不想这样做。 这会让我伤心。

我在更改字符串时检查了DOM,看起来React会很乐意更改最后一个文本节点,因为我追加到字符串,它只会在我创建一个额外的<span>时添加回车。这正如我所料(并希望)。

但是我也可以想象这种对<tt>的可变调用可能会以某种方式混淆差异算法 - 毕竟,在渲染数组时我们通常需要createElement。 我只是不知道那是什么或影响是什么。

那么这样安全吗?好吗?还有其他方法吗?

1 个答案:

答案 0 :(得分:0)

JSX只是React.createElement的语法糖。 React真的不关心(或知道)你是否手动编写React.createElement

  

但是我也可以想象这种对createElement的可变调用可能会以某种方式混淆差异算法 - 毕竟,在渲染数组时我们通常需要键。

是和否。你在做什么在JSX中等同于这个。

<parent>
  <child1 />
  <child2 />
</parent>

即。你只需要一个带有多个&#34;直接&#34;孩子,而不是传给孩子一个阵列。您之前可能已经看过这个,因为这很常见,因此您的解决方案对于React而言并不比使用JSX更糟糕。

请注意,任何元素都可以拥有密钥。如果传递数组,React只会强制执行它。

现在问题是,使用key有什么好处(见下一节)。

  

我只是不知道那是什么或影响是什么。

您可能想阅读https://facebook.github.io/react/docs/reconciliation.html。引用相关部分:

  

List-wise diff

     

有问题的案例

     

为了让孩子和解,React采用了一种非常天真的方法。它会同时覆盖两个孩子的列表,并在出现差异时生成突变。

     

例如,如果在末尾添加元素:

renderA: <div><span>first</span></div>
renderB: <div><span>first</span><span>second</span></div>
=> [insertNode <span>second</span>]
     

在开头插入元素是有问题的。 React将看到两个节点都是跨距,因此会进入突变模式。

renderA: <div><span>first</span></div>
renderB: <div><span>second</span><span>first</span></div>
=> [replaceAttribute textContent 'second'], [insertNode <span>first</span>]
     

有许多算法试图找到转换元素列表的最小操作集。 Levenshtein距离可以在O(n2)中使用单个元素插入,删除和替换找到最小值。即使我们使用Levenshtein,当节点移动到另一个位置时,这并不能找到,并且算法的复杂程度要差得多。

     

     

为了解决这个看似棘手的问题,我们引入了一个可选属性。您可以为每个孩子提供用于进行匹配的密钥。如果你指定一个键,React现在能够找到插入,删除,替换并使用哈希表在O(n)中移动。

renderA: <div><span key="first">first</span></div>
renderB: <div><span key="second">second</span><span key="first">first</span></div>
=> [insertNode <span>second</span>]
     

在实践中,找到钥匙并不是很难。大多数情况下,您要显示的元素已经具有唯一ID。如果情况并非如此,您可以向模型添加新的ID属性,或者对内容的某些部分进行哈希以生成密钥。请记住,密钥只能在其兄弟姐妹中独一无二,而不是全局唯一。