我刚刚开始学习React和JavaScript。在我阅读了文档和教程之后,我看了一些示例项目,并尝试找出我还没有得到的内容。
然后我看到有render()
函数内部定义的函数,以及render()
函数之外的函数。
E.g。在render()
之外:
handleClick(e) {
e.preventDefault();
e.target.parentElement.classList.toggle('open');
}
和里面的render()......
const divider = (divider, key) => {
const classes = classNames( 'divider', divider.class);
return (<li key={key} className={ classes }></li>);
};
为什么它们看起来如此不同?你为什么要在render()
之外有一些函数?
编辑:
render()
之外的函数的另一个示例:
hideMobile() {
if (document.body.classList.contains('sidebar-mobile-show')) {
document.body.classList.toggle('sidebar-mobile-show')
}
}
EDIT2:在另一个线程中,有人回答说,如果函数背后的逻辑很重,那么它应该在render()之外。但是为什么你想在render()中使用函数呢?
答案 0 :(得分:2)
首先,如果我们想在开始时构建一个Clock,那么我们就尝试使用无状态函数对象创建一个面向对象,可维护的组件。
function Clock(props) {
return (
<div>
<h1>Hello, world!</h1>
<h2>It is {props.date.toLocaleTimeString()}.</h2>
</div>
);
}
function tick() {
ReactDOM.render(
<Clock date={new Date()} />,
document.getElementById('root')
);
}
setInterval(tick, 1000);
引自doc
使Clock组件真正可重用和封装。它会 设置自己的计时器并每秒更新一次。
... 理想情况下,我们想要写一次并自己更新时钟......
所以这里是React的精神,我们希望将这个函数对象转换为一个可以自我维护的类,所以现在我们涉及render()
,更具体地说我们涉及有状态组件在:
Add a single empty method to it called render()
...
Clock is now defined as a class rather than a function.
然后我们得到:
class Clock extends React.Component {
constructor(props) {
super(props);
this.state = {date: new Date()};
this.clockCore = this.clockCore.bind(this);
}
componentDidMount() {
this.timerID = setInterval(
() => this.tick(),
1000
);
}
tick() {
this.setState({
date: new Date()
});
}
clockCore() {
return (<div>
<h2>It is {this.state.date.toLocaleTimeString()}.</h2>
</div>);
}
render() {
return this.clockCore();
}
}
如您所知,如果render()
需要刷新组件的状态,则会再次触发setState()
。
<强>更新强>
在我看来,没有必要在render()
中定义该功能。
我对上面的原始示例进行了一些修改,以表明这一点。
从您提供的示例中,divider的用法可能如下:
const divider = (divider, key) => {
const classes = classNames( 'divider', divider.class);
return (<li key={key} className={ classes }></li>);
};
return (<ul>{this.state.dividerList?
this.state.dividerList.forEach(divider) : null}</ul>);
我认为这样做的原因只是为了可维护性,有人可能希望所有DOM在render()
内部创建代码,以便在返回的DOM结构非常复杂时(以及arrow function is lightweight)轻松跟踪,但是因为我说这是主观的,它确实可以在外面定义。
在这种情况下,我曾经在下面执行,看起来你提供的内容更优雅,但如果你在render()
之外定义了这个功能,事情会变得分散注意力对我来说。
let dividers = [];
if (this.state.dividerList) {
this.state.dividerList.forEach((divider, key) => {
let classes = classNames( 'divider', divider.class);
dividers.push((<li key={key} className={ classes }></li>));
});
}
return (<ul>{dividers}</ul>);
因此,您提供的另一个针对DOM操作功能的功能是完全正确的,并且可以在外部定义。
答案 1 :(得分:1)
render()
更改时都会调用{p> state
。因此,每次state
更改时,保留在render函数内的每个函数都将创建为一个新函数。这意味着每次重新渲染时都会重新创建divider
。
handleClick
是一个普通的对象函数。
在render
函数内写的函数通常是那些处理组件重新渲染的函数。
答案 2 :(得分:0)
除此之外,handleClick
是为每个对象/组件创建和访问的函数,divide
是本地范围的函数,它们的功能几乎相同。但是,divider
将在每个渲染上创建为新函数,这可能具有后续性能影响,而handleClick
为已定义组件(对象)创建一次。