Разница между декларативным и императивным в React.js?


97

Недавно я много изучал функциональность и способы использования JavaScript-библиотеки Facebook React.js. Говоря о его отличиях от остального мира JavaScript, часто упоминаются два стиля программирования declarativeи imperative.

В чем разница между ними?


22
latentflip.com/imperative-vs-declarative Imperative programming: telling the "machine" how to do something, and as a result what you want to happen will happen. Declarative programming: telling the "machine"1 what you would like to happen, and let the computer figure out how to do it.
rickyduck

4
Тайлер МакГиннис написал об этом длинную статью с несколькими хорошими примерами.
Ян Данн,

Зачем добавлять длинный ответ в качестве комментария? ..
Alex

1
Ссылка выше верна, но косая черта в конце ссылки вызывает ошибку
Джеймс Ю

Ответы:


167

Декларативный стиль, подобный тому, что имеет response, позволяет вам управлять потоком и состоянием в вашем приложении, говоря: «Это должно выглядеть так». Императивный стиль меняет ситуацию и позволяет вам управлять своим приложением, говоря: «Это то, что вы должны делать».

Преимущество декларативного подхода в том, что вы не увязнете в деталях реализации представления состояния. Вы делегируете организационный компонент согласованности представлений приложения, поэтому вам просто нужно беспокоиться о состоянии.

Представьте, что у вас есть дворецкий, который является своего рода метафорой каркаса. И вы хотите приготовить ужин. В императивном мире вы пошагово объясните им, как приготовить ужин. Вы должны предоставить следующие инструкции:

Go to the kitchen
Open fridge
Remove chicken from fridge
...
Bring food to the table

В декларативном мире вы просто описываете то, что хотите

I want dinner with chicken.

Если ваш дворецкий не знает, как приготовить курицу, вы не можете действовать декларативно. Точно так же, как если Backbone не знает, как изменить себя для выполнения определенной задачи, вы не можете просто сказать ему, чтобы она выполняла эту задачу. React может быть декларативным, потому что, например, он «умеет делать курицу». По сравнению с Backbone, который умеет взаимодействовать только с кухней.

Возможность описать состояние значительно уменьшает площадь обнаружения ошибок, что является преимуществом. С другой стороны, у вас может быть меньше гибкости в том, как что-то происходит, потому что вы делегируете или абстрагируетесь от того, как вы реализуете состояние.


78

Представьте себе простой компонент пользовательского интерфейса, например кнопку «Нравится». Когда вы нажимаете на него, он становится синим, если раньше был серым, и серым, если раньше был синим.

Обязательный способ сделать это:

if( user.likes() ) {
    if( hasBlue() ) {
        removeBlue();
        addGrey();
    } else {
        removeGrey();
        addBlue();
    }
}

По сути, вы должны проверить, что в настоящее время находится на экране, и обработать все изменения, необходимые для его перерисовки с текущим состоянием, включая отмену изменений из предыдущего состояния. Вы можете себе представить, насколько сложно это могло быть в реальном сценарии.

Напротив, декларативный подход был бы следующим:

if( this.state.liked ) {
    return <blueLike />;
} else {
    return <greyLike />;
}

Поскольку декларативный подход разделяет проблемы, эта его часть должна обрабатывать только то, как пользовательский интерфейс должен выглядеть в определенном состоянии, и, следовательно, ее гораздо проще понять.


21

Это отличная аналогия:

* Обязательный ответ : выйдите из северного выхода с парковки и поверните налево. Двигайтесь по автомагистрали I-15 на юг, пока не дойдете до съезда с шоссе Bangerter. Сверните направо с выхода, как будто вы собираетесь в Икеа. Идите прямо и на первом светофоре поверните направо. Продолжайте движение к следующему светофору, затем поверните налево. Мой дом № 298.

Декларативный ответ : Мой адрес: 298 West Immutable Alley, Draper Utah 84020 *.

https://tylermcginnis.com/imperative-vs-declarative-programming/


18

Лучше всего сравнить React (декларативный) и JQuery (императивный), чтобы показать вам различия.

В React вам нужно только описать конечное состояние вашего пользовательского интерфейса в render()методе, не беспокоясь о том, как перейти из предыдущего состояния пользовательского интерфейса в новое состояние пользовательского интерфейса. Например,

render() {
  const { price, volume } = this.state;
  const totalPrice = price * volume;

  return (
    <div>
      <Label value={price} className={price > 100 ? 'expensive' : 'cheap'} ... />
      <Label value={volume} className={volume > 1000 ? 'high' : 'low'} ... />
      <Label value={totalPrice} ... />
      ...
    </div>
  )
}

С другой стороны, JQuery требует от вас обязательного перехода состояния пользовательского интерфейса, например, выбора элементов метки и обновления их текста и CSS:

updatePrice(price) {
  $("#price-label").val(price);
  $("#price-label").toggleClass('expansive', price > 100);
  $("#price-label").toggleClass('cheap', price < 100);

  // also remember to update UI depending on price 
  updateTotalPrice();
  ... 
}

updateVolume(volume) {
  $("#volume-label").val(volume);
  $("#volume-label").toggleClass('high', volume > 1000);
  $("#volume-label").toggleClass('low', volume < 1000);
  
  // also remember to update UI depending on volume
  updateTotalPrice();
  ... 
}

updateTotalPrice() {
  const totalPrice = price * volume;
  $("#total-price-label").val(totalPrice);
  ...
}

В реальном сценарии будет обновляться гораздо больше элементов пользовательского интерфейса, а также их атрибуты (например, стили CSS и прослушиватели событий) и т. Д. Если вы сделаете это в обязательном порядке с помощью JQuery, это станет сложным и утомительным; легко забыть обновить некоторые части пользовательского интерфейса или забыть удалить старые обработчики событий (вызвать утечку памяти или срабатывание обработчика несколько раз) и т. д. Именно здесь возникают ошибки, т. е. состояние пользовательского интерфейса и состояние модели выходят за рамки синхронизировать.

Состояния рассинхронизации никогда не произойдут с декларативным подходом React, потому что нам нужно только обновить состояние модели, а React отвечает за синхронизацию пользовательского интерфейса и состояний модели.

  • Под крюком React обновит все измененные элементы DOM, используя императивный код.

Вы также можете прочитать мой ответ на вопрос: В чем разница между декларативным и императивным программированием? .

PS: из приведенного выше примера jQuery вы можете подумать, что, если мы поместим все манипуляции с DOM в updateAll()метод и будем вызывать его каждый раз, когда любое из наших состояний модели изменяется, и пользовательский интерфейс никогда не будет рассинхронизирован. Вы правы, и это фактически то, что делает React, с той лишь разницей, что jQuery updateAll()вызовет множество ненужных манипуляций с DOM, но React будет обновлять только измененные элементы DOM, используя свой алгоритм Virtual DOM Diffing .


6

Императивный код указывает JavaScript, как он должен выполнять каждый шаг. С помощью декларативного кода мы сообщаем JavaScript, что мы хотим сделать, и позволяем JavaScript позаботиться о выполнении шагов.

React является декларативным, потому что мы пишем код, который нам нужен, а React отвечает за принятие нашего объявленного кода и выполнение всех шагов JavaScript / DOM для достижения желаемого результата.


5

Реальная параллель в императивном мире - это войти в бар за пивом и дать следующие инструкции бармену:

- Возьмите стакан с полки

- Поставьте стекло перед сквозняком

- Опустите ручку вниз, пока стакан не наполнится

- Передай мне стакан.

Вместо этого в декларативном мире вы бы просто сказали: «Пиво, пожалуйста».

Декларативный подход к запросу пива предполагает, что бармен знает, как его подать, и это важный аспект работы декларативного программирования.

В декларативном программировании разработчики описывают только то, чего они хотят достичь, и нет необходимости перечислять все шаги, чтобы это работало.

Тот факт, что React предлагает декларативный подход, упрощает его использование, и, следовательно, результирующий код прост, что часто приводит к меньшему количеству ошибок и большей простоте обслуживания.

Поскольку React следует декларативной парадигме, и нет необходимости указывать ему, как взаимодействовать с DOM; вы просто ОБЪЯВЛЯЕТЕ, что вы хотите видеть на экране, и React сделает всю работу за вас.


1

Декларативное программирование - это парадигма программирования ... которая выражает логику вычисления без описания его потока управления.

Императивное программирование - это парадигма программирования, в которой используются операторы, изменяющие состояние программы.

ссылка: - https://codeburst.io/declarative-vs-imperative-programming-a8a7c93d9ad2


0

Я начну с аналогии: у меня две машины, в двух моих машинах я хочу, чтобы температура в моей машине была нормальной комнатной, ~ 72 ° F. В первом (старом) автомобиле есть две ручки для управления температурой (1 ручка для управления температурой и 1 ручка для управления воздушным потоком). Когда становится слишком жарко, я должен отрегулировать первую ручку, чтобы снизить температуру и, возможно, изменить воздушный поток) и наоборот, если слишком холодно. Это обязательная работа! Я должен сам управлять ручками. В моей второй (более новой) машине я могу установить / объявить температуру. Это означает, что мне не нужно возиться с ручками, чтобы отрегулировать температуру, которую моя машина знает, я объявляю / устанавливаю ее на 72 ° F, и моя машина сделает всю необходимую работу, чтобы добраться до этого состояния.

React такой же, вы объявляете разметку / шаблон и stat, а затем React выполняет обязательную работу, чтобы поддерживать DOM в синхронизации с вашим приложением.

<button onClick={activateTeleporter}>Activate Teleporter</button>

Вместо того, .addEventListener()чтобы использовать для настройки обработки событий, мы объявляем то, что хотим. Когда кнопка нажата, она запускает activateTeleporterфункцию.


-1
  • Декларативная позволяет вам контролировать весь вид. (вроде как госуправление)
  • Императив позволяет вам контролировать вид. (например, как $ (это))
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.