【发布时间】:2021-08-01 21:58:36
【问题描述】:
如果这是一个多余的问题,请原谅我,但我在任何地方都找不到我的用例的确切答案。
我正在 React 中制作一个打字机效果组件,纯粹是为了好玩。我已经设法让它以我喜欢的方式与类组件一起工作,但我更愿意将它改编为函数组件,以此作为更好地熟悉函数组件的机会,但它的行为似乎很奇怪一个区间。我以前用过很多不同的方式使用函数组件,但由于某种原因,这让我很难过。
这是jsfiddle with the class component.
class Typewriter extends React.Component {
state = {
showCursor: false,
displayMsgs: []
}
constructor(props) {
super(props)
this.typeSpeed = this.props.typeSpeed ? this.props.typeSpeed : 250
this.curChar = 0
this.msgLength = this.props.msg.length
this.chunks = [{msg: '', flags: {color: "black"}}]
this.curChunk = 0
this.inChunk = false
for(let i = 0; i < this.msgLength; i++) {
if(this.props.msg.charAt(i) === '\\') {
this.curChunk += 1
this.inChunk = !this.inChunk
let flags = { color: "black" }
if(this.inChunk) {
switch(this.props.msg.charAt(i + 1)) {
case "R":
flags = { color: "red" }
break
default:
break
}
}
this.chunks.push({msg: '', flags: flags})
i += 2
}
this.chunks[this.curChunk].msg += this.props.msg.charAt(i)
}
this.curChunk = 0
console.log(this.chunks)
}
componentDidMount() {
const displayMsgs = (new Array(this.chunks.length)).fill("")
this.setState({ displayMsgs: displayMsgs })
const cursorInterval = setInterval(() => {
this.setState({showCursor: !this.state.showCursor})
}, 250)
const interval = setInterval(() => {
const newDisplay = this.state.displayMsgs.map((el, i) => (
i === this.curChunk ? this.state.displayMsgs[this.curChunk] + this.chunks[this.curChunk].msg.charAt(this.curChar)
: el
))
this.setState({displayMsgs: newDisplay})
this.curChar += 1
if(this.curChar >= this.chunks[this.curChunk].msg.length) {
this.curChar = 0
this.curChunk += 1
console.log(this.curChunk)
}
if(this.curChunk >= this.chunks.length)
end()
}, this.typeSpeed)
const skipTyping = () => {
clearInterval(interval)
let newDisplay = []
for(let i = 0; i < this.state.displayMsgs.length; i++){
newDisplay.push(this.chunks[i].msg)
}
this.setState({ displayMsgs: newDisplay })
end()
}
const end = () => {
clearInterval(interval)
clearInterval(cursorInterval)
document.removeEventListener("keypress", skipTyping)
document.removeEventListener("click", skipTyping)
this.setState({showCursor: false})
if(this.props.callback)
this.props.callback()
}
document.addEventListener("keypress", skipTyping)
document.addEventListener("click", skipTyping)
}
render() {
return (
<div>
{ this.state.displayMsgs.map((msg, i) =>
(
<span key={i} style={{ color: this.chunks[i].flags.color }}>{msg}</span>
)
)}
{ this.state.showCursor && <span>|</span>}
</div>
)
}
}
ReactDOM.render(<Typewriter msg="Test message. As you can see it \Rworks\R smoothly." typeSpeed={50} />, document.querySelector("#app"))
它运行顺利,正如我所期望的那样,我可以轻松地在 componentDidMount 函数。这个组件也适用于传递的回调,允许我在一个更大的应用程序中链接多个 Typewriter 对象。
相反,我似乎无法让钩子在这种情况下工作。我使用了 Dan Abramov 的自定义钩子 useInterval,但它的行为不稳定,并且看起来比类组件更复杂。这里是jsfiddle with the functional component.,我只是让它以一种丑陋的方式工作,没有按键跳过输入等。
如您所见,功能组件在更新时非常不稳定;完成输入后,光标会以预期的间隔/平滑度闪烁。出于这个原因,我怀疑渲染中发生了一些有趣的事情,导致性能受到重大影响,我只是无法弄清楚。非常感谢任何见解。
【问题讨论】:
标签: node.js reactjs react-hooks