ΠΠ΅ΡΠ΅Π΄Π°ΡΠ° ΡΡΠ½ΠΊΡΠΈΠΉ Π² ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½ΡΡ
ΠΠ°ΠΊ ΠΏΠ΅ΡΠ΅Π΄Π°ΡΡ ΠΎΠ±ΡΠ°Π±ΠΎΡΡΠΈΠΊ ΡΠΎΠ±ΡΡΠΈΡ (Π½Π°ΠΏΡΠΈΠΌΠ΅Ρ, onClick) ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½ΡΡ?
ΠΠ΅ΡΠ΅Π΄Π°Π²Π°ΠΉΡΠ΅ ΠΎΠ±ΡΠ°Π±ΠΎΡΡΠΈΠΊΠΈ ΡΠΎΠ±ΡΡΠΈΠΉ ΠΈ Π΄ΡΡΠ³ΠΈΠ΅ ΡΡΠ½ΠΊΡΠΈΠΈ ΡΠ΅ΡΠ΅Π· ΠΏΡΠΎΠΏΡΡ Π΄ΠΎΡΠ΅ΡΠ½ΠΈΠΌ ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½ΡΠ°ΠΌ:
<button onClick={this.handleClick}>
ΠΡΠ»ΠΈ Π²Ρ Ρ ΠΎΡΠΈΡΠ΅ ΠΈΠΌΠ΅ΡΡ Π΄ΠΎΡΡΡΠΏ ΠΊ ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½ΡΡ-ΡΠΎΠ΄ΠΈΡΠ΅Π»Ρ ΡΠ΅ΡΠ΅Π· ΠΎΠ±ΡΠ°Π±ΠΎΡΡΠΈΠΊ, Π²Π°ΠΌ Π½ΡΠΆΠ½ΠΎ ΠΏΡΠΈΠ²ΡΠ·Π°ΡΡ ΡΡΠ½ΠΊΡΠΈΡ ΠΊ ΡΠΊΠ·Π΅ΠΌΠΏΠ»ΡΡΡ ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½ΡΠ° (ΡΠΌ. Π½ΠΈΠΆΠ΅).
ΠΠ°ΠΊ ΠΏΡΠΈΠ²ΡΠ·Π°ΡΡ ΡΡΠ½ΠΊΡΠΈΡ ΠΊ ΡΠΊΠ·Π΅ΠΌΠΏΠ»ΡΡΡ ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½ΡΠ°?
Π Π·Π°Π²ΠΈΡΠΈΠΌΠΎΡΡΠΈ ΠΎΡ ΡΠΎΠ³ΠΎ, ΠΊΠ°ΠΊΠΎΠΉ ΡΠΈΠ½ΡΠ°ΠΊΡΠΈΡ ΠΈ ΠΏΠΎΠ΄Ρ
ΠΎΠ΄ ΠΊ ΡΠΎΠ·Π΄Π°Π½ΠΈΡ ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½ΡΠΎΠ² Π²Ρ ΠΈΡΠΏΠΎΠ»ΡΠ·ΡΠ΅ΡΠ΅, ΡΡΡΠ΅ΡΡΠ²ΡΠ΅Ρ Π½Π΅ΡΠΊΠΎΠ»ΡΠΊΠΎ ΡΠΏΠΎΡΠΎΠ±ΠΎΠ² ΡΠ΄ΠΎΡΡΠΎΠ²Π΅ΡΠΈΡΡΡΡ, ΡΡΠΎ ΡΡΠ½ΠΊΡΠΈΠΈ ΠΈΠΌΠ΅ΡΡ Π΄ΠΎΡΡΡΠΏ ΠΊ ΡΠ°ΠΊΠΈΠΌ Π°ΡΡΠΈΠ±ΡΡΠ°ΠΌ ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½ΡΠ°, ΠΊΠ°ΠΊ this.props
ΠΈ this.state
.
ΠΡΠΈΠ²ΡΠ·ΠΊΠ° Π² ΠΊΠΎΠ½ΡΡΡΡΠΊΡΠΎΡΠ΅ (ES2015)
class Foo extends Component {
constructor(props) {
super(props);
this.handleClick = this.handleClick.bind(this);
}
handleClick() {
console.log('ΠΠΎ ΠΊΠ½ΠΎΠΏΠΊΠ΅ ΠΊΠ»ΠΈΠΊΠ½ΡΠ»ΠΈ');
}
render() {
return <button onClick={this.handleClick}>ΠΠ°ΠΆΠΌΠΈ Π½Π° ΠΌΠ΅Π½Ρ</button>;
}
}
Π‘Π²ΠΎΠΉΡΡΠ²Π° ΠΊΠ»Π°ΡΡΠ° (ES2022)
class Foo extends Component {
handleClick = () => {
console.log('ΠΠΎ ΠΊΠ½ΠΎΠΏΠΊΠ΅ ΠΊΠ»ΠΈΠΊΠ½ΡΠ»ΠΈ');
};
render() {
return <button onClick={this.handleClick}>ΠΠ°ΠΆΠΌΠΈ Π½Π° ΠΌΠ΅Π½Ρ</button>;
}
}
ΠΡΠΈΠ²ΡΠ·ΠΊΠ° Π² ΠΌΠ΅ΡΠΎΠ΄Π΅ render()
class Foo extends Component {
handleClick() {
console.log('ΠΠΎ ΠΊΠ½ΠΎΠΏΠΊΠ΅ ΠΊΠ»ΠΈΠΊΠ½ΡΠ»ΠΈ');
}
render() {
return <button onClick={this.handleClick.bind(this)}>ΠΠ°ΠΆΠΌΠΈ Π½Π° ΠΌΠ΅Π½Ρ</button>;
}
}
ΠΡΠΈΠΌΠ΅ΡΠ°Π½ΠΈΠ΅:
ΠΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°Π½ΠΈΠ΅
Function.prototype.bind
Π² render() ΡΠΎΠ·Π΄Π°ΡΡ Π½ΠΎΠ²ΡΡ ΡΡΠ½ΠΊΡΠΈΡ ΠΏΡΠΈ ΠΊΠ°ΠΆΠ΄ΠΎΠΌ ΡΠ΅Π½Π΄Π΅ΡΠ΅ ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½ΡΠ°, ΡΡΠΎ ΠΌΠΎΠΆΠ΅Ρ ΠΏΠΎΠ²Π»ΠΈΡΡΡ Π½Π° ΠΏΡΠΎΠΈΠ·Π²ΠΎΠ΄ΠΈΡΠ΅Π»ΡΠ½ΠΎΡΡΡ (ΡΠΌ. Π½ΠΈΠΆΠ΅).
Π‘ΡΡΠ΅Π»ΠΎΡΠ½Π°Ρ ΡΡΠ½ΠΊΡΠΈΡ Π² render()
class Foo extends Component {
handleClick() {
console.log('ΠΠΎ ΠΊΠ½ΠΎΠΏΠΊΠ΅ ΠΊΠ»ΠΈΠΊΠ½ΡΠ»ΠΈ');
}
render() {
return <button onClick={() => this.handleClick()}>ΠΠ°ΠΆΠΌΠΈ Π½Π° ΠΌΠ΅Π½Ρ</button>;
}
}
ΠΡΠΈΠΌΠ΅ΡΠ°Π½ΠΈΠ΅:
ΠΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°Π½ΠΈΠ΅ ΡΡΡΠ΅Π»ΠΎΡΠ½ΠΎΠΉ ΡΡΠ½ΠΊΡΠΈΠΈ Π² render() ΡΠΎΠ·Π΄Π°ΡΡ Π½ΠΎΠ²ΡΡ ΡΡΠ½ΠΊΡΠΈΡ ΠΏΡΠΈ ΠΊΠ°ΠΆΠ΄ΠΎΠΉ ΠΎΡΡΠΈΡΠΎΠ²ΠΊΠ΅ ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½ΡΠ°, ΡΡΠΎ ΠΌΠΎΠΆΠ΅Ρ Π½Π°ΡΡΡΠ°ΡΡ ΠΎΠΏΡΠΈΠΌΠΈΠ·Π°ΡΠΈΠΈ, ΠΈΡΠΏΠΎΠ»ΡΠ·ΡΡΡΠΈΠ΅ ΡΡΡΠΎΠ³ΠΎΠ΅ ΡΡΠ°Π²Π½Π΅Π½ΠΈΠ΅ Π΄Π»Ρ ΠΎΠΏΡΠ΅Π΄Π΅Π»Π΅Π½ΠΈΡ ΠΈΠ΄Π΅Π½ΡΠΈΡΠ½ΠΎΡΡΠΈ.
ΠΠΎΠΆΠ½ΠΎ Π»ΠΈ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΡ ΡΡΡΠ΅Π»ΠΎΡΠ½ΡΠ΅ ΡΡΠ½ΠΊΡΠΈΠΈ Π² ΠΌΠ΅ΡΠΎΠ΄Π΅ render()?
Π ΡΠ΅Π»ΠΎΠΌ, Π΄Π°. ΠΠ°ΡΠ°ΡΡΡΡ ΡΡΠΎ ΡΠ°ΠΌΡΠΉ ΠΏΡΠΎΡΡΠΎΠΉ ΡΠΏΠΎΡΠΎΠ± ΠΏΠ΅ΡΠ΅Π΄Π°ΡΡ ΠΏΠ°ΡΠ°ΠΌΠ΅ΡΡΡ ΡΠ΅ΡΠ΅Π· ΠΊΠΎΠ»Π±ΡΠΊΠΈ.
ΠΡΠ»ΠΈ ΠΆΠ΅ Ρ Π²Π°Ρ Π²ΠΎΠ·Π½ΠΈΠΊΠ»ΠΈ ΠΏΡΠΎΠ±Π»Π΅ΠΌΡ Ρ ΠΏΡΠΎΠΈΠ·Π²ΠΎΠ΄ΠΈΡΠ΅Π»ΡΠ½ΠΎΡΡΡΡ β ΠΎΠΏΡΠΈΠΌΠΈΠ·ΠΈΡΡΠΉΡΠ΅!
ΠΠ°ΡΠ΅ΠΌ Π²ΠΎΠΎΠ±ΡΠ΅ Π½ΡΠΆΠ½Π° ΠΏΡΠΈΠ²ΡΠ·ΠΊΠ°?
Π JavaScript ΡΡΠΈ Π΄Π²Π° ΡΡΠ°Π³ΠΌΠ΅Π½ΡΠ° ΠΊΠΎΠ΄Π° Π½Π΅ ΡΠ°Π²Π½ΠΎΠ·Π½Π°ΡΠ½Ρ:
obj.method();
var method = obj.method;
method();
ΠΡΠΈΠ²ΡΠ·ΠΊΠ° Π³Π°ΡΠ°Π½ΡΠΈΡΡΠ΅Ρ, ΡΡΠΎ Π²ΡΠΎΡΠΎΠΉ ΡΡΠ°Π³ΠΌΠ΅Π½Ρ Π±ΡΠ΄Π΅Ρ ΡΠ°Π±ΠΎΡΠ°ΡΡ ΡΠ°ΠΊ ΠΆΠ΅, ΠΊΠ°ΠΊ ΠΈ ΠΏΠ΅ΡΠ²ΡΠΉ.
Π React, ΠΊΠ°ΠΊ ΠΏΡΠ°Π²ΠΈΠ»ΠΎ, ΠΏΡΠΈΠ²ΡΠ·ΡΠ²Π°ΡΡ Π½ΡΠΆΠ½ΠΎ ΡΠΎΠ»ΡΠΊΠΎ ΡΠ΅ ΠΌΠ΅ΡΠΎΠ΄Ρ, ΠΊΠΎΡΠΎΡΡΠ΅ Π²Ρ Ρ
ΠΎΡΠΈΡΠ΅ ΠΏΠ΅ΡΠ΅Π΄Π°ΡΡ Π΄ΡΡΠ³ΠΈΠΌ ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½ΡΠ°ΠΌ. ΠΠ°ΠΏΡΠΈΠΌΠ΅Ρ, <button onClick={this.handleClick}>
ΠΏΠ΅ΡΠ΅Π΄Π°ΡΡ this.handleClick
, ΠΏΠΎΡΡΠΎΠΌΡ Π΅Π³ΠΎ Π½ΡΠΆΠ½ΠΎ ΠΏΡΠΈΠ²ΡΠ·Π°ΡΡ. ΠΠΏΡΠΎΡΠ΅ΠΌ, ΠΌΠ΅ΡΠΎΠ΄ render
ΠΈ ΠΌΠ΅ΡΠΎΠ΄Ρ ΠΆΠΈΠ·Π½Π΅Π½Π½ΠΎΠ³ΠΎ ΡΠΈΠΊΠ»Π° ΠΏΡΠΈΠ²ΡΠ·ΡΠ²Π°ΡΡ Π½Π΅ ΠΎΠ±ΡΠ·Π°ΡΠ΅Π»ΡΠ½ΠΎ, ΡΠ°ΠΊ ΠΊΠ°ΠΊ ΠΌΡ Π½Π΅ ΠΏΠ΅ΡΠ΅Π΄Π°ΡΠΌ ΠΈΡ
Π² Π΄ΡΡΠ³ΠΈΠ΅ ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½ΡΡ.
ΠΠ·Π½Π°ΠΊΠΎΠΌΡΡΠ΅ΡΡ ΡΠΎ ΡΡΠ°ΡΡΡΠΉ ΠΠ΅Ρ ΡΠ΄Ρ ΠΠ°ΡΡ, Π² ΠΊΠΎΡΠΎΡΠΎΠΉ Π±ΠΎΠ»Π΅Π΅ ΠΏΠΎΠ΄ΡΠΎΠ±Π½ΠΎ ΠΎΠ±ΡΡΡΠ½Π΅Π½ΠΎ, ΡΡΠΎ ΡΠ°ΠΊΠΎΠ΅ ΠΏΡΠΈΠ²ΡΠ·ΠΊΠ°, ΠΈ ΠΊΠ°ΠΊ ΡΠ°Π±ΠΎΡΠ°ΡΡ ΡΡΠ½ΠΊΡΠΈΠΈ Π² JavaScript.
ΠΠΎΡΠ΅ΠΌΡ ΠΌΠΎΡ ΡΡΠ½ΠΊΡΠΈΡ Π²ΡΠ·ΡΠ²Π°Π΅ΡΡΡ ΠΊΠ°ΠΆΠ΄ΡΠΉ ΡΠ°Π· ΠΏΡΠΈ ΠΎΡΡΠΈΡΠΎΠ²ΠΊΠ΅ ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½ΡΠ°?
Π£Π±Π΅Π΄ΠΈΡΠ΅ΡΡ, ΡΡΠΎ Π²Ρ Π½Π΅ Π²ΡΠ·ΡΠ²Π°Π΅ΡΠ΅ ΡΡΠ½ΠΊΡΠΈΡ, ΠΊΠΎΠ³Π΄Π° ΠΏΠ΅ΡΠ΅Π΄Π°ΡΡΠ΅ Π΅Ρ ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½ΡΡ:
render() {
// ΠΠ΅ΠΏΡΠ°Π²ΠΈΠ»ΡΠ½ΠΎ: Π²ΠΌΠ΅ΡΡΠΎ ΡΡΡΠ»ΠΊΠΈ Π±ΡΠ»Π° Π²ΡΠ·Π²Π°Π½Π° ΡΡΠ½ΠΊΡΠΈΡ handleClick!
return <button onClick={this.handleClick()}>ΠΠ°ΠΆΠΌΠΈ Π½Π° ΠΌΠ΅Π½Ρ</button>
}
ΠΠΌΠ΅ΡΡΠΎ ΡΡΠΎΠ³ΠΎ ΠΏΠ΅ΡΠ΅Π΄Π°ΠΉΡΠ΅ ΡΠ°ΠΌΡ ΡΡΠ½ΠΊΡΠΈΡ (Π±Π΅Π· ΡΠΊΠΎΠ±ΠΎΠΊ):
render() {
// ΠΡΠ°Π²ΠΈΠ»ΡΠ½ΠΎ: handleClick ΠΏΠ΅ΡΠ΅Π΄Π°ΡΡΡΡ ΠΊΠ°ΠΊ ΡΡΡΠ»ΠΊΠ°!
return <button onClick={this.handleClick}>ΠΠ°ΠΆΠΌΠΈ Π½Π° ΠΌΠ΅Π½Ρ</button>
}
ΠΠ°ΠΊ ΠΏΠ΅ΡΠ΅Π΄Π°ΡΡ ΠΏΠ°ΡΠ°ΠΌΠ΅ΡΡΡ ΠΎΠ±ΡΠ°Π±ΠΎΡΡΠΈΠΊΡ ΡΠΎΠ±ΡΡΠΈΠΉ ΠΈΠ»ΠΈ ΠΊΠΎΠ»Π±ΡΠΊΡ?
Π§ΡΠΎΠ±Ρ ΠΏΠ΅ΡΠ΅Π΄Π°ΡΡ ΠΏΠ°ΡΠ°ΠΌΠ΅ΡΡΡ ΠΎΠ±ΡΠ°Π±ΠΎΡΡΠΈΠΊΡ ΡΠΎΠ±ΡΡΠΈΠΉ, ΠΎΠ±Π΅ΡΠ½ΠΈΡΠ΅ Π΅Π³ΠΎ Π² ΡΡΡΠ΅Π»ΠΎΡΠ½ΡΡ ΡΡΠ½ΠΊΡΠΈΡ:
<button onClick={() => this.handleClick(id)} />
ΠΡΠΎ Π΄Π΅ΠΉΡΡΠ²ΠΈΠ΅ ΡΠ°Π²Π½ΠΎΡΠΈΠ»ΡΠ½ΠΎ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°Π½ΠΈΡ .bind
:
<button onClick={this.handleClick.bind(this, id)} />
ΠΡΠΈΠΌΠ΅Ρ: ΠΠ΅ΡΠ΅Π΄Π°ΡΠ° ΠΏΠ°ΡΠ°ΠΌΠ΅ΡΡΠΎΠ² Ρ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°Π½ΠΈΠ΅ΠΌ ΡΡΡΠ΅Π»ΠΎΡΠ½ΡΡ ΡΡΠ½ΠΊΡΠΈΠΉ
const A = 65 // ASCII-ΠΊΠΎΠ΄ ΡΠΈΠΌΠ²ΠΎΠ»Π°
class Alphabet extends React.Component {
constructor(props) {
super(props);
this.state = {
justClicked: null,
letters: Array.from({length: 26}, (_, i) => String.fromCharCode(A + i))
};
}
handleClick(letter) {
this.setState({ justClicked: letter });
}
render() {
return (
<div>
Just clicked: {this.state.justClicked}
<ul>
{this.state.letters.map(letter =>
<li key={letter} onClick={() => this.handleClick(letter)}>
{letter}
</li>
)}
</ul>
</div>
)
}
}
ΠΡΠΈΠΌΠ΅Ρ: ΠΠ΅ΡΠ΅Π΄Π°ΡΠ° ΠΏΠ°ΡΠ°ΠΌΠ΅ΡΡΠΎΠ² Ρ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°Π½ΠΈΠ΅ΠΌ Π°ΡΡΠΈΠ±ΡΡΠΎΠ² Π΄Π°Π½Π½ΡΡ
Π ΠΊΠ°ΡΠ΅ΡΡΠ²Π΅ Π°Π»ΡΡΠ΅ΡΠ½Π°ΡΠΈΠ²Π½ΠΎΠ³ΠΎ ΠΏΠΎΠ΄Ρ ΠΎΠ΄Π° Π²Ρ ΠΌΠΎΠΆΠ΅ΡΠ΅ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΡ DOM API, ΡΡΠΎΠ±Ρ Ρ ΡΠ°Π½ΠΈΡΡ Π½Π΅ΠΎΠ±Ρ ΠΎΠ΄ΠΈΠΌΡΠ΅ Π΄Π»Ρ ΠΎΠ±ΡΠ°Π±ΠΎΡΡΠΈΠΊΠΎΠ² ΡΠΎΠ±ΡΡΠΈΠΉ Π΄Π°Π½Π½ΡΠ΅. Π Π°ΡΡΠΌΠΎΡΡΠΈΡΠ΅ ΡΡΠΎΡ ΠΏΠΎΠ΄Ρ ΠΎΠ΄, Π΅ΡΠ»ΠΈ Π²Π°ΠΌ Π½ΡΠΆΠ½ΠΎ ΠΎΠΏΡΠΈΠΌΠΈΠ·ΠΈΡΠΎΠ²Π°ΡΡ Π±ΠΎΠ»ΡΡΠΎΠ΅ ΠΊΠΎΠ»ΠΈΡΠ΅ΡΡΠ²ΠΎ ΡΠ»Π΅ΠΌΠ΅Π½ΡΠΎΠ² ΠΈΠ»ΠΈ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΡ Π΄Π΅ΡΠ΅Π²ΠΎ Π²ΠΈΠ·ΡΠ°Π»ΠΈΠ·Π°ΡΠΈΠΈ, ΠΏΠΎΠ»Π°Π³Π°ΡΡΠ΅Π΅ΡΡ Π½Π° ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ React.PureComponent Π΄Π»Ρ ΠΏΡΠΎΠ²Π΅ΡΠΊΠΈ Π½Π° ΡΠ°Π²Π΅Π½ΡΡΠ²ΠΎ.
const A = 65 // ASCII-ΠΊΠΎΠ΄ ΡΠΈΠΌΠ²ΠΎΠ»Π°
class Alphabet extends React.Component {
constructor(props) {
super(props);
this.handleClick = this.handleClick.bind(this);
this.state = {
justClicked: null,
letters: Array.from({length: 26}, (_, i) => String.fromCharCode(A + i))
};
}
handleClick(e) {
this.setState({
justClicked: e.target.dataset.letter
});
}
render() {
return (
<div>
Just clicked: {this.state.justClicked}
<ul>
{this.state.letters.map(letter =>
<li key={letter} data-letter={letter} onClick={this.handleClick}>
{letter}
</li>
)}
</ul>
</div>
)
}
}
ΠΠ°ΠΊ ΠΏΡΠ΅Π΄ΠΎΡΠ²ΡΠ°ΡΠΈΡΡ ΡΠ»ΠΈΡΠΊΠΎΠΌ Π±ΡΡΡΡΡΠΉ ΠΈΠ»ΠΈ ΡΠ»ΠΈΡΠΊΠΎΠΌ ΡΠ°ΡΡΡΠΉ Π²ΡΠ·ΠΎΠ² ΡΡΠ½ΠΊΡΠΈΠΈ?
ΠΡΠ»ΠΈ Π²Ρ ΠΈΡΠΏΠΎΠ»ΡΠ·ΡΠ΅ΡΠ΅ ΠΎΠ±ΡΠ°Π±ΠΎΡΡΠΈΠΊΠΈ ΡΠΎΠ±ΡΡΠΈΠΉ, ΡΠ°ΠΊΠΈΠ΅ ΠΊΠ°ΠΊ onClick
ΠΈΠ»ΠΈ onScroll
, ΠΈ Ρ
ΠΎΡΠΈΡΠ΅ ΠΏΡΠ΅Π΄ΠΎΡΠ²ΡΠ°ΡΠΈΡΡ Π±ΡΡΡΡΠΎΠ΅ ΡΡΠ°Π±Π°ΡΡΠ²Π°Π½ΠΈΠ΅ ΠΊΠΎΠ»Π±ΡΠΊΠΎΠ², Π²Ρ ΠΌΠΎΠΆΠ΅ΡΠ΅ ΠΎΠ³ΡΠ°Π½ΠΈΡΠΈΡΡ ΡΠΊΠΎΡΠΎΡΡΡ Π²ΡΠΏΠΎΠ»Π½Π΅Π½ΠΈΡ ΠΊΠΎΠ»Π±ΡΠΊΠ°. ΠΠ»Ρ ΡΡΠΎΠ³ΠΎ Π²Ρ ΠΌΠΎΠΆΠ΅ΡΠ΅ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΡ:
- ΡΡΠΎΡΡΠ»ΠΈΠ½Π³: Π²ΡΠ±ΠΎΡΠΎΡΠ½ΡΠ΅ ΠΈΠ·ΠΌΠ΅Π½Π΅Π½ΠΈΡ, Π·Π°Π²ΠΈΡΠΈΠΌΡΠ΅ ΠΎΡ ΡΠ°ΡΡΠΎΡΡ, ΠΎΡΠ½ΠΎΠ²Π°Π½Π½ΠΎΠΉ Π½Π° Π²ΡΠ΅ΠΌΠ΅Π½ΠΈ (Π½Π°ΠΏΡ.
_.throttle
) - Π΄Π΅Π±Π°ΡΠ½ΡΠΈΠ½Π³: ΠΈΠ·ΠΌΠ΅Π½Π΅Π½ΠΈΡ, Π·Π°Π΄Π΅ΠΉΡΡΠ²ΠΎΠ²Π°Π½Π½ΡΠ΅ ΠΏΠΎΡΠ»Π΅ Π½Π΅ΠΊΠΎΠ³ΠΎ ΠΏΠ΅ΡΠΈΠΎΠ΄Π° Π±Π΅Π·Π΄Π΅ΠΉΡΡΠ²ΠΈΡ (Π½Π°ΠΏΡ.
_.debounce
) - ΡΡΠΎΡΡΠ»ΠΈΠ½Π³ Ρ ΠΏΠΎΠΌΠΎΡΡΡ
requestAnimationFrame
: Π²ΡΠ±ΠΎΡΠΎΡΠ½ΡΠ΅ ΠΈΠ·ΠΌΠ΅Π½Π΅Π½ΠΈΡ, ΠΎΡΠ½ΠΎΠ²Π°Π½Π½ΡΠ΅ Π½Π°requestAnimationFrame
(Π½Π°ΠΏΡ.raf-schd
)
ΠΠ·Π³Π»ΡΠ½ΠΈΡΠ΅ Π½Π° Π²ΠΈΠ·ΡΠ°Π»ΠΈΠ·Π°ΡΠΈΡ, ΠΊΠΎΡΠΎΡΠ°Ρ ΡΡΠ°Π²Π½ΠΈΠ²Π°Π΅Ρ ΡΡΠ½ΠΊΡΠΈΠΈ throttle
ΠΈ debounce
.
ΠΡΠΈΠΌΠ΅ΡΠ°Π½ΠΈΠ΅:
_.debounce
,_.throttle
ΠΈraf-schd
ΠΏΡΠ΅Π΄ΡΡΠΌΠ°ΡΡΠΈΠ²Π°ΡΡ ΠΌΠ΅ΡΠΎΠ΄cancel
Π΄Π»Ρ ΠΎΡΠΌΠ΅Π½Ρ ΠΎΡΠ»ΠΎΠΆΠ΅Π½Π½ΡΡ ΠΊΠΎΠ»Π±ΡΠΊΠΎΠ². ΠΡ Π΄ΠΎΠ»ΠΆΠ½Ρ Π»ΠΈΠ±ΠΎ Π²ΡΠ·Π²Π°ΡΡ ΡΡΠΎΡ ΠΌΠ΅ΡΠΎΠ΄ ΠΈΠ· componentWillUnmount, Π»ΠΈΠ±ΠΎ ΡΠ΄ΠΎΡΡΠΎΠ²Π΅ΡΠΈΡΡΡΡ, ΡΡΠΎ ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ Π²ΡΡ Π΅ΡΡ Π²ΡΡΡΠΎΠ΅Π½ Π² ΠΏΡΠ΅Π΄Π΅Π»Π°Ρ ΠΎΡΠ»ΠΎΠΆΠ΅Π½Π½ΠΎΠΉ ΡΡΠ½ΠΊΡΠΈΠΈ.
Throttle
Π’ΡΠΎΡΡΠ»ΠΈΠ½Π³ ΠΏΡΠ΅Π΄ΠΎΡΠ²ΡΠ°ΡΠ°Π΅Ρ ΠΏΠΎΠ²ΡΠΎΡΠ½ΡΠΉ Π²ΡΠ·ΠΎΠ² ΡΡΠ½ΠΊΡΠΈΠΈ Π² Π·Π°Π΄Π°Π½Π½ΡΠΉ ΠΏΠ΅ΡΠΈΠΎΠ΄ Π²ΡΠ΅ΠΌΠ΅Π½ΠΈ. ΠΡΠΎΡ ΠΌΠ΅ΡΠΎΠ΄ Π±ΡΠ» Π·Π°Π΄Π΅ΠΉΡΡΠ²ΠΎΠ²Π°Π½ Π² ΠΏΡΠΈΠΌΠ΅ΡΠ΅ Π½ΠΈΠΆΠ΅, ΡΡΠΎΠ±Ρ Π½Π΅ Π΄ΠΎΠΏΡΡΡΠΈΡΡ Π²ΡΠ·ΠΎΠ² ΠΎΠ±ΡΠ°Π±ΠΎΡΡΠΈΠΊΠ° Β«clickΒ» ΡΠ°ΡΠ΅ ΡΠ΅ΠΌ ΡΠ°Π· Π² ΡΠ΅ΠΊΡΠ½Π΄Ρ.
import throttle from 'lodash.throttle';
class LoadMoreButton extends React.Component {
constructor(props) {
super(props);
this.handleClick = this.handleClick.bind(this);
this.handleClickThrottled = throttle(this.handleClick, 1000);
}
componentWillUnmount() {
this.handleClickThrottled.cancel();
}
render() {
return <button onClick={this.handleClickThrottled}>ΠΠ°Π³ΡΡΠ·ΠΈΡΡ Π΅ΡΡ</button>;
}
handleClick() {
this.props.loadMore();
}
}
Debounce
ΠΠ΅Π±Π°ΡΠ½ΡΠΈΠ½Π³ Π³Π°ΡΠ°Π½ΡΠΈΡΡΠ΅Ρ, ΡΡΠΎ ΡΡΠ½ΠΊΡΠΈΡ Π½Π΅ Π±ΡΠ΄Π΅Ρ Π²ΡΠΏΠΎΠ»Π½ΡΡΡΡΡ Π΄ΠΎ ΡΠ΅Ρ ΠΏΠΎΡ, ΠΏΠΎΠΊΠ° Π½Π΅ ΠΏΡΠΎΠΉΠ΄ΡΡ ΠΎΠΏΡΠ΅Π΄Π΅Π»ΡΠ½Π½ΠΎΠ΅ ΠΊΠΎΠ»ΠΈΡΠ΅ΡΡΠ²ΠΎ Π²ΡΠ΅ΠΌΠ΅Π½ΠΈ Ρ ΠΌΠΎΠΌΠ΅Π½ΡΠ° Π΅Ρ ΠΏΠΎΡΠ»Π΅Π΄Π½Π΅Π³ΠΎ Π²ΡΠ·ΠΎΠ²Π°. ΠΡΠΎΡ ΠΌΠ΅ΡΠΎΠ΄ ΠΏΡΠΈΠ³ΠΎΠ΄ΠΈΡΡΡ, Π΅ΡΠ»ΠΈ Π²Π°ΠΌ Π½ΡΠΆΠ½ΠΎ ΠΏΡΠΎΠ²Π΅ΡΡΠΈ ΡΠ΅ΡΡΡΡΠΎΡΠΌΠΊΠΈΠΉ ΡΠ°ΡΡΡΡ Π² ΠΎΡΠ²Π΅Ρ Π½Π° ΡΠΎΠ±ΡΡΠΈΠ΅, ΠΊΠΎΡΠΎΡΠΎΠ΅ ΠΌΠΎΠΆΠ΅Ρ Π±ΡΡΡΡΠΎ ΠΏΠΎΠ²ΡΠΎΡΠΈΡΡΡΡ (Π½Π°ΠΏΡΠΈΠΌΠ΅Ρ, ΠΏΡΠΎΠΊΡΡΡΠΊΠ° ΡΡΡΠ°Π½ΠΈΡΡ ΠΈΠ»ΠΈ Π½Π°ΠΆΠ°ΡΠΈΠ΅ ΠΊΠ»Π°Π²ΠΈΡ). Π ΠΏΡΠΈΠΌΠ΅ΡΠ΅ Π½ΠΈΠΆΠ΅ Π΄Π»Ρ Π²Π²ΠΎΠ΄Π° ΡΠ΅ΠΊΡΡΠ° ΠΈΡΠΏΠΎΠ»ΡΠ·ΡΠ΅ΡΡΡ Π·Π°Π΄Π΅ΡΠΆΠΊΠ° Π² 250 ΠΌΡ.
import debounce from 'lodash.debounce';
class Searchbox extends React.Component {
constructor(props) {
super(props);
this.handleChange = this.handleChange.bind(this);
this.emitChangeDebounced = debounce(this.emitChange, 250);
}
componentWillUnmount() {
this.emitChangeDebounced.cancel();
}
render() {
return (
<input
type="text"
onChange={this.handleChange}
placeholder="ΠΠΎΠΈΡΠΊ..."
defaultValue={this.props.value}
/>
);
}
handleChange(e) {
this.emitChangeDebounced(e.target.value);
}
emitChange(value) {
this.props.onChange(value);
}
}
requestAnimationFrame
throttling
requestAnimationFrame
β ΡΡΠΎ ΡΠΏΠΎΡΠΎΠ± ΠΎΡΠ³Π°Π½ΠΈΠ·Π°ΡΠΈΠΈ ΠΎΡΠ΅ΡΠ΅Π΄ΠΈ ΡΡΠ½ΠΊΡΠΈΠΈ, ΠΊΠΎΡΠΎΡΠ°Ρ Π±ΡΠ΄Π΅Ρ Π²ΡΠΏΠΎΠ»Π½Π΅Π½Π° Π² Π±ΡΠ°ΡΠ·Π΅ΡΠ΅ Π·Π° ΠΎΠΏΡΠΈΠΌΠ°Π»ΡΠ½ΠΎΠ΅ Π²ΡΠ΅ΠΌΡ Π΄Π»Ρ ΠΏΡΠΎΠΈΠ·Π²ΠΎΠ΄ΠΈΡΠ΅Π»ΡΠ½ΠΎΡΡΠΈ ΠΎΡΡΠΈΡΠΎΠ²ΠΊΠΈ. Π€ΡΠ½ΠΊΡΠΈΡ, ΠΏΠΎΡΡΠ°Π²Π»Π΅Π½Π½Π°Ρ Π² ΠΎΡΠ΅ΡΠ΅Π΄Ρ Ρ ΠΏΠΎΠΌΠΎΡΡΡ requestAnimationFrame
, Π·Π°ΠΏΡΡΡΠΈΡΡΡ Π² ΡΠ»Π΅Π΄ΡΡΡΠ΅ΠΌ ΠΊΠ°Π΄ΡΠ΅. ΠΡΠ°ΡΠ·Π΅Ρ ΠΏΡΠΈΠ»ΠΎΠΆΠΈΡ Π²ΡΠ΅ ΡΡΠΈΠ»ΠΈΡ, ΡΡΠΎΠ±Ρ ΠΎΠ±Π΅ΡΠΏΠ΅ΡΠΈΡΡ 60 ΠΊΠ°Π΄ΡΠΎΠ² Π² ΡΠ΅ΠΊΡΠ½Π΄Ρ (60 fps β frames per second). ΠΠ΄Π½Π°ΠΊΠΎ, Π΅ΡΠ»ΠΈ Π±ΡΠ°ΡΠ·Π΅Ρ Π½Π΅ Π² ΡΠΎΡΡΠΎΡΠ½ΠΈΠΈ ΡΠΏΡΠ°Π²ΠΈΡΡΡΡ Ρ ΡΡΠΎΠΉ Π·Π°Π΄Π°ΡΠ΅ΠΉ, ΠΎΠ½ Π΅ΡΡΠ΅ΡΡΠ²Π΅Π½Π½ΡΠΌ ΠΎΠ±ΡΠ°Π·ΠΎΠΌ ΠΎΠ³ΡΠ°Π½ΠΈΡΠΈΡ ΠΊΠΎΠ»ΠΈΡΠ΅ΡΡΠ²ΠΎ ΠΊΠ°Π΄ΡΠΎΠ² Π² ΡΠ΅ΠΊΡΠ½Π΄Ρ. ΠΠ°ΠΏΡΠΈΠΌΠ΅Ρ, Π΅ΡΠ»ΠΈ Π²Π°ΡΠ΅ ΡΡΡΡΠΎΠΉΡΡΠ²ΠΎ ΠΏΠΎΠ΄Π΄Π΅ΡΠΆΠΈΠ²Π°Π΅Ρ ΡΠΎΠ»ΡΠΊΠΎ 30 fps, ΡΠΎ ΠΈ ΠΏΠΎΠ»ΡΡΠΈΡΠ΅ Π²Ρ ΡΠΎΠ»ΡΠΊΠΎ 30 ΠΊΠ°Π΄ΡΠΎΠ². ΠΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°Π½ΠΈΠ΅ requestAnimationFrame
Π΄Π»Ρ ΡΡΠΎΡΡΠ»ΠΈΠ½Π³Π° ΡΠ²Π»ΡΠ΅ΡΡΡ ΠΎΡΠ΅Π½Ρ ΠΏΠΎΠ»Π΅Π·Π½ΡΠΌ ΠΌΠ΅ΡΠΎΠ΄ΠΎΠΌ, ΡΠ°ΠΊ ΠΊΠ°ΠΊ ΠΏΠΎΠΌΠΎΠ³Π°Π΅Ρ ΠΏΡΠ΅Π΄ΠΎΡΠ²ΡΠ°ΡΠΈΡΡ Π²ΡΠΏΠΎΠ»Π½Π΅Π½ΠΈΠ΅ Π±ΠΎΠ»Π΅Π΅ 60 ΠΎΠ±Π½ΠΎΠ²Π»Π΅Π½ΠΈΠΉ Π² ΡΠ΅ΠΊΡΠ½Π΄Ρ. ΠΡΠ»ΠΈ Π²Ρ Π²ΡΠΏΠΎΠ»Π½ΡΠ΅ΡΠ΅ 100 ΠΎΠ±Π½ΠΎΠ²Π»Π΅Π½ΠΈΠΉ Π² ΡΠ΅ΠΊΡΠ½Π΄Ρ, ΡΡΠΎ ΡΠΎΠ·Π΄Π°ΡΡ Π»ΠΈΡΠ½ΡΡ ΡΠ°Π±ΠΎΡΡ Π΄Π»Ρ Π±ΡΠ°ΡΠ·Π΅ΡΠ°, ΠΊΠΎΡΠΎΡΡΡ ΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΠ΅Π»Ρ Π²ΡΡ ΡΠ°Π²Π½ΠΎ Π½Π΅ Π·Π°ΠΌΠ΅ΡΠΈΡ.
ΠΡΠΈΠΌΠ΅ΡΠ°Π½ΠΈΠ΅:
ΠΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°Π½ΠΈΠ΅ ΡΡΠΎΠΉ ΡΠ΅Ρ Π½ΠΈΠΊΠΈ Π·Π°Ρ Π²Π°ΡΠΈΡ ΡΠΎΠ»ΡΠΊΠΎ ΠΏΠΎΡΠ»Π΅Π΄Π½Π΅Π΅ ΠΎΠΏΡΠ±Π»ΠΈΠΊΠΎΠ²Π°Π½Π½ΠΎΠ΅ Π·Π½Π°ΡΠ΅Π½ΠΈΠ΅ Π² ΠΊΠ°Π΄ΡΠ΅. ΠΡΠΈΠΌΠ΅Ρ ΡΠ°Π±ΠΎΡΡ Π΄Π°Π½Π½ΠΎΠΉ ΠΎΠΏΡΠΈΠΌΠΈΠ·Π°ΡΠΈΠΈ Π²Ρ ΠΌΠΎΠΆΠ΅ΡΠ΅ ΡΠ²ΠΈΠ΄Π΅ΡΡ Π½Π°
MDN
import rafSchedule from 'raf-schd';
class ScrollListener extends React.Component {
constructor(props) {
super(props);
this.handleScroll = this.handleScroll.bind(this);
// Π‘ΠΎΠ·Π΄Π°ΡΠΌ Π½ΠΎΠ²ΡΡ ΡΡΠ½ΠΊΡΠΈΡ Π΄Π»Ρ ΠΏΠ»Π°Π½ΠΈΡΠΎΠ²Π°Π½ΠΈΡ ΠΎΠ±Π½ΠΎΠ²Π»Π΅Π½ΠΈΠΉ.
this.scheduleUpdate = rafSchedule(
point => this.props.onScroll(point)
);
}
handleScroll(e) {
// ΠΠ»Π°Π½ΠΈΡΡΠ΅ΠΌ ΠΎΠ±Π½ΠΎΠ²Π»Π΅Π½ΠΈΠ΅ ΠΏΡΠΈ Π°ΠΊΡΠΈΠ²ΠΈΠ·Π°ΡΠΈΠΈ ΡΠΎΠ±ΡΡΠΈΡ ΠΏΡΠΎΠΊΡΡΡΠΊΠΈ.
// ΠΡΠ»ΠΈ Π² ΡΠ°ΠΌΠΊΠ°Ρ
ΠΊΠ°Π΄ΡΠ° ΠΌΡ ΠΏΠΎΠ»ΡΡΠ°Π΅ΠΌ ΠΌΠ½ΠΎΠ³ΠΎ ΠΎΠ±Π½ΠΎΠ²Π»Π΅Π½ΠΈΠΉ, ΠΏΡΠ±Π»ΠΈΠΊΡΠ΅ΠΌ ΡΠΎΠ»ΡΠΊΠΎ ΠΏΠΎΡΠ»Π΅Π΄Π½Π΅Π΅ Π·Π½Π°ΡΠ΅Π½ΠΈΠ΅.
this.scheduleUpdate({ x: e.clientX, y: e.clientY });
}
componentWillUnmount() {
// ΠΡΠΌΠ΅Π½ΡΠ΅ΠΌ Π»ΡΠ±ΡΠ΅ ΠΎΠΆΠΈΠ΄Π°ΡΡΠΈΠ΅ ΠΎΠ±Π½ΠΎΠ²Π»Π΅Π½ΠΈΡ, ΡΠ°ΠΊ ΠΊΠ°ΠΊ ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ Π±ΡΠ΄Π΅Ρ Π΄Π΅ΠΌΠΎΠ½ΡΠΈΡΠΎΠ²Π°Π½.
this.scheduleUpdate.cancel();
}
render() {
return (
<div
style={{ overflow: 'scroll' }}
onScroll={this.handleScroll}
>
<img src="/my-huge-image.jpg" />
</div>
);
}
}
Π’Π΅ΡΡΠΈΡΠΎΠ²Π°Π½ΠΈΠ΅ ΠΎΠ³ΡΠ°Π½ΠΈΡΠ΅Π½ΠΈΡ ΡΠΊΠΎΡΠΎΡΡΠΈ
ΠΠΎΠ³Π΄Π° Π²Ρ ΡΠ΅ΡΡΠΈΡΡΠ΅ΡΠ΅, ΡΡΠΎ Π²Π°Ρ ΠΊΠΎΠ΄ ΠΎΠ³ΡΠ°Π½ΠΈΡΠ΅Π½ΠΈΡ ΡΠΊΠΎΡΠΎΡΡΠΈ ΡΠ°Π±ΠΎΡΠ°Π΅Ρ ΠΏΡΠ°Π²ΠΈΠ»ΡΠ½ΠΎ, ΠΏΠΎΠ»Π΅Π·Π½ΠΎ ΠΈΠΌΠ΅ΡΡ Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎΡΡΡ ΠΏΡΠΎΠΊΡΡΡΠΈΡΡ Π²ΡΠ΅ΠΌΡ. ΠΡΠ»ΠΈ Π²Ρ ΠΈΡΠΏΠΎΠ»ΡΠ·ΡΠ΅ΡΠ΅ jest
, Π²Π°ΠΌ ΠΌΠΎΠΆΠ΅Ρ ΠΏΡΠΈΠ³ΠΎΠ΄ΠΈΡΡΡΡ mock timers
. ΠΡΠ»ΠΈ Π²Ρ ΠΈΡΠΏΠΎΠ»ΡΠ·ΡΠ΅ΡΠ΅ requestAnimationFrame
, ΡΠΎ raf-stub
ΠΌΠΎΠΆΠ΅Ρ ΠΎΠΊΠ°Π·Π°ΡΡΡΡ ΠΏΠΎΠ»Π΅Π·Π½ΡΠΌ ΠΈΠ½ΡΡΡΡΠΌΠ΅Π½ΡΠΎΠΌ Π΄Π»Ρ ΡΠΏΡΠ°Π²Π»Π΅Π½ΠΈΡ ΡΠΌΠ΅Π½Ρ ΠΊΠ°Π΄ΡΠΎΠ² Π°Π½ΠΈΠΌΠ°ΡΠΈΠΈ.