我正在尝试使用React实现语法高亮显示。语法highligher组件本身与Redux无关,但Redux仍然相关。
荧光笔需要两个道具
structure
- 这是一个二维数组,其中包含要呈现的标记的id,分割为行,例如:
const structure = [
[ // a line
"ryMtafN9b",
"r1WftTfEcZ",
"rkfftaMV5W"
],
[ // another line
"B1sGYTG4cZ",
"By3MYpzEq-"
],
...
]
tokens
- 令牌ID和令牌之间的映射,例如:
const tokens = {
"ryMtafN9b": {
"type": "LEFT_SQUARE_BRACKET",
"value": "[",
"id": "ryMtafN9b"
},
"r1WftTfEcZ": {
"type": "WHITESPACE",
"value": " ",
"id": "r1WftTfEcZ"
},
"rkfftaMV5W": {
"type": "LEFT_CURLY_BRACKET",
"value": "{",
"id": "rkfftaMV5W"
},
...
}
然后渲染就像这样(删除所有不相关的东西):
一个标记
class TokenElement extends PureComponent {
render() {
// return a <span> based on the token type, etc
}
}
一行(行)
class TokenRow extends PureComponent {
render() {
const { tokens } = this.props
return (<div>
{tokens.map((token) => <TokenElement token={token} key={token.id} />)}
</div>)
}
}
实际的荧光笔组件
class JsonSyntaxHighlighter extends PureComponent {
render() {
const { tokens, structure } = this.props
return (<pre>
{
structure.map((line) => (<TokenRow tokens={line.map((tokenId) => tokens[tokenId])} />))
}
</pre>)
}
}
问题
我实现自定义语法高亮显示的原因是因为我需要根据异步中的数据在令牌级别添加自定义装饰。这些更新以扩展tokens
对象中的每个标记的形式出现,而不通过reducer进行突变(整个荧光笔组件由连接的智能组件呈现)。即使所有组件都是PureComponent
s,因此重新呈现一个令牌需要很长时间:
JsonSyntaxHighlighter
检查是否需要更新 - 是(因为tokens
对象已更改其道具)TokenRow
检查是否需要更新 - 是(因为它的tokens
数组已更改,因为它是map
ping的结果)TokenElement
检查是否需要更新 MAYBE (因为现在我可以正确依赖shouldComponentUpdate
。)现在当很多这些小更新以相对较小的间隔到达时,UI就会阻塞,因为大量的重新渲染排队了。
问题 我可以更好地构建我的数据或组件,以便频繁更改单个令牌的状态可以快速触发渲染,而无需检查整个树吗?
答案 0 :(得分:0)
Facebook has a great article on exactly this topic.
简短回答是慷慨地使用React的shouldComponentUpdate
生命周期方法来指定整个组件树何时应该避免更新。 Here are a few examples on how to do that.
答案 1 :(得分:0)
我没有正确的代码示例(这里发布的代码太多了)但是我最终解决这个问题的方法是使用Observable
s({{}将大量的商店更新批处理为块。 1}},rxjs
运算符)。这使得reducer代码更加复杂,因为状态合并不是那么自然,但现在我可以完全控制商店更新发生的频率,这意味着可以控制buffer
发生的频率。