написать впереди
Эта статья подходит для новичков, если вы старый игрок в React, вы можетеbreak
Или проверить на пропуски.
Вот некоторые распространенные ошибки новичков и методы оптимизации:
Почему вам нужно оптимизировать
Я всегда считал, что оптимизация производительности — это кумулятивный процесс, который проходит через каждую строчку кода, который вы пишете. Если не обращать внимания на оптимизацию, то это может и не быть большой проблемой, но никто не знает, какое предложение станет той соломинкой, которая сломает хребет верблюду и заставит мир взорваться💥.
Ниже приведен текст, я надеюсь, что он может вам помочь.
Фокус оптимизации React
Ядро оптимизации производительности реагирования:
Уменьшите количество рендеров! отложить или амортизировать рендер
Причина в том, что большая часть накладных расходов на реакцию генерируется в период рендеринга, в процессе рендеринга будет много копирования объектов, и в то же время будет сгенерировано много фрагментированных объектов (элементов реакции), которые используется для сравнения с предыдущим объектом и каждый раз генерируется при рендеринге.
Ввиду этой особенности, некоторые часто используемые методы оптимизации резюмируются:
Пример оптимизации
- согласно с
props
Модуль инициализации
пример:
class Page extends Component (props) {
state = {
a: 1
}
componentDidMount() {
this.setState({
a: this.props.a
})
}
}
Очевидная ошибка — модифицировать компонент дважды в жизненном цикле, хотя это соответствует времени модификации состояния (componentDidMount
Внутреннее измененное состояние), но вы должны подумать о том, есть ли подозрение на избыточное вторичное рендеринг, это должно быть непосредственноconstructor
внутренняя инициализация (также больше соответствует буквальному определению «инициализации»).
оптимизация:
class Page extends Component (props) {
constructor(props) {
super(props)
this.state = {
a: props.a
}
}
}
- наследовать
PureComponent
пример:
class Page extends Component (props) {
constructor(props) {
super(props)
this.state = {
a: props.a
}
}
}
Тамprops
Приходит и не используетсяshouldComponentUpdate
использовать в случаеPureComponent
может эффективно уменьшитьrender
количество раз, которое по существу использует компонентshouldComponentUpdate(newProps, newState)
жизненный цикл, вrender
Сравнить доprops、 state
(поверхностное сравнение), если изменений нет, то и обновляться не будет.
оптимизация:
class Page extends PureComponent (props) {
constructor(props) {
super(props)
this.state = {
a: props.a
}
}
}
- использовать
shouldComponentUpdate
пример:
class Page extends Component (props) {
constructor(props) {
super(props)
const { a, b } = props.data;
this.state = {
a,
b
}
}
render() {
const { a } = this.props.data;
return <div>{a}</div>
}
}
На протяженииrender
нужно толькоa
не используется в случаеshouldComponentUpdate
, а обновления компонентов обычно проходят в новом объекте, еслиa
значение не изменилось, что привело бы к бессмысленномуrerender
.
оптимизация:
class Page extends Component (props) {
constructor(props) {
super(props)
const { a, b } = props.data;
this.state = {
a,
b
}
}
shouldComponentUpdate(newProps, newState) {
if (newProps.data.a !== this.props.data.a) {
return true;
}
return false;
}
render() {
const { a } = this.props.data;
return <div>{a}</div>
}
}
- Разумное разделение компонентов для сложных страниц
пример:
class Page extends PureComponent (props) {
constructor(props) {
super(props)
this.state = {
a: 1,
...
}
}
render() {
const { a } = this.props.data;
return <div>
{...}
</div>
}
}
реагироватьdiff
Сравнение ведется в единицах компонентов.Страница тоже большой компонент.Все данные находятся на одной странице,и любое изменение состояния приведет к обновлению всей страницы. Разумно разделить компоненты и объединитьPureComponent
Определение компонентов может сократить количество рендерингов неизмененных частей страницы и в то же времяdiff
Степень детализации сравнения выше.
оптимизация:
class Page extends PureComponent (props) {
constructor(props) {
super(props)
this.state = {
a: 1,
b: 2
}
}
render() {
const { a } = this.props.data;
return <div>
<Component1 a={a} />
<Component2 b={b} />
...
</div>
}
}
-
существует(Как напомнили друзья в области комментариев, поскольку componentWillMount react16.3 был помечен как небезопасный жизненный цикл, он будет удален в 17, поэтому эта статья больше не рекомендуется, спасибо @Flasco напоминание)componentDidMount
Периодически вызывайте интерфейс и возвращайтесь послеsetState
пример:
class Page extends PureComponent (props) {
constructor(props) {
this.state = {
a: 1
}
}
componentDidMount() {
this.getData()
}
getData async() {
const result = await API.getData();
this.setState({
a: result.a
})
}
}
react подчеркивает, что его нельзя использовать вcomponentWillMount
Измените состояние в , но здесь необходимо учитывать, что вызывающий интерфейс является асинхронной операцией, и все асинхронные операции на веб-стороне будут выполняться после завершения синхронной операции, поэтому в случае вызовов интерфейса или других асинхронных операции, вы можетеcomponentWillMount
Вызов интерфейса в обратном вызове и запись изменения состояния в обратном вызове может ускорить время отклика.
оптимизация:
class Page extends PureComponent (props) {
constructor(props) {
this.state = {
a: 1
}
}
componentWillMount() {
this.getData()
}
getData async() {
const result = await API.getData();
this.setState({
a: result.a
})
}
}
- Не определяйте функции в jsx
пример:
class Page extends PureComponent (props) {
render() {
return (
<div onClick={() => {
...
}}/>
)
}
}
Функция, определенная в методе рендеринга, будет переопределяться при каждом обновлении компонента, и каждый раз, когда определение будет повторно применяться к блоку памяти, что приведет к увеличению использования памяти, запуск сборки мусора js также увеличит накладные расходы и серьезно повлияет на производительность. представление. Функции должны храниться в экземплярах, постоянных методах и памяти, быть привязанными или использоваться в рендеринге.
оптимизация:
class Page extends PureComponent (props) {
onClick = () => {
...
}
render() {
return (
<div onClick={this.onClick}/>
)
}
}
- Не связывайте это в jsx
пример:
class Page extends PureComponent (props) {
onClick() {
...
}
render() {
return (
<div onClick={this.onClick.bind(this)}/>
)
}
}
Хотя функция определена и сохранена в экземпляре, метод привязки вернет новую функцию, что также увеличивает использование памяти и накладные расходы на сборку мусора. Вы можете определить функцию непосредственно как функцию стрелки или использовать привязку в конструкторе, чтобы изменить ее на точку.
оптимизация:
class Page extends PureComponent (props) {
constructor(props) {
super(props)
this.state = {
...
}
this.onBindClick = this.onBindClick.bind(this)
}
onClick = () => {
...
}
onBindClick() {
...
}
render() {
return (
<div onClick={this.onClick}>
<div onClick={this.onBindClick}/>
</div>
)
}
}
- добросовестное использование ссылки
пример:
const SLIDER_WEIGHT = 200
class Page extends PureComponent (props) {
constructor(props) {
super(props)
this.state = {
left: 0
}
}
componentDidMount() {
this.initSwiper()
}
initSwiper = () => {
this.intervalId = setInterval(() => {
this.setState((state) => ({
left: left + SLIDER_WEIGHT
})))
}, 2000)
}
render() {
const { left } = this.state
return (
<div>
<div style={{left: left + 'px'}}>
...
</div>
</div>
)
}
}
Предположим, что здесь должна быть реализована карта карусели, и для достижения эффекта карусели она часто модифицируется в таймере цикла.state
, каждый раз, когда состояние компонента обновляется, это приводит к частому отображению компонента. В настоящее время вы можете использовать ref для изменения стиля dom без запуска обновлений компонентов.
оптимизация:
пример:
const SLIDER_WEIGHT = 200
class Page extends PureComponent (props) {
left = 0
componentDidMount() {
this.initSwiper()
}
initSwiper = () => {
this.intervalId = setInterval(() => {
this.left += SLIDER_WEIGHT
this.refs.swiper.style.left = this.left + 'px'
}, 2000)
}
render() {
const { left } = this.state
return (
<div>
<div ref="swiper">
...
</div>
</div>
)
}
}
- Использование фрагментов
пример:
() => <div>
<div>content1</div>
<div>content2</div>
</div>
Когда вы пишете отдельный компонент, если вы обнаружите, что самый внешний элемент по существу избыточен, но дочерний элемент имеет несколько тегов, которые не могут быть представлены напрямую, вы должны использовать Fragment, пустой тег jsx. Это позволит отображать на один тег меньше и сделает наш код более лаконичным.
оптимизация:
пример:
() => <>
<div>content1</div>
<div>content2</div>
</>
точки оптимизации реакции
上文中几条优化方法同样适用于react-native,因为它们有着同样的抽象层,但是react-native有一些独特的优化技巧,提供给即将需要写native的同学😏
-
Используйте анимированные анимации для выполнения некоторых функций изначально. Можно понимать как анимацию CSS3, базовая оптимизация и более простая реализация делают меня счастливым.
-
Подумайте, можете ли вы использовать более качественные компоненты: listView, Flatlist... и атрибуты: pagesize, removeClippedSubviews..., что также удобно благодаря базовой оптимизации.
-
Используйте Interactionmanager, чтобы организовать трудоемкую работу после завершения всех взаимодействий или анимаций, а затем выполнить распределение накладных расходов (узкое место в производительности, вызванное взаимодействием между нативным js и нативным кодом) и выполнить обратный вызов в Interactionmanager.runAfterInteractions().
Выше приведены некоторые точки оптимизации производительности react/react-native, которые я обобщил.Если у вас есть другие решения, пожалуйста, оставьте сообщение ниже, и я добавлю его вовремя.Наконец, я желаю всем писать код без ошибок и всегда иметь лучшую производительность.
//
// _ooOoo_
// o8888888o
// 88" . "88
// (| -_- |)
// O\ = /O
// ____/`---'\____
// .' \\| |// `.
// / \\||| : |||// \
// / _||||| -:- |||||- \
// | | \\\ - /// | |
// | \_| ''\---/'' | |
// \ .-\__ `-` ___/-. /
// ___`. .' /--.--\ `. . __
// ."" '< `.___\_<|>_/___.' >'"".
// | | : `- \`.;`\ _ /`;.`/ - ` : | |
// \ \ `-. \_ __\ /__ _/ .-` / /
// ======`-.____`-.___\_____/___.-`____.-'======
// `=---='
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
// 佛祖保佑 永无BUG
-- The end