Разница между декларативным и императивным в React.js?
Недавно я много изучал функциональность и способы использования JavaScript-библиотеки Facebook React.js. Говоря о его различиях с остальным миром JavaScript часто два стиля программирования declarative
а также imperative
упоминаются.
В чем разница между обоими?
15 ответов
Декларативный стиль, подобный тому, который имеет реакция, позволяет вам контролировать поток и состояние в вашем приложении, говоря: "Это должно выглядеть так". Императивный стиль переворачивает это и позволяет вам контролировать свое приложение, говоря: "Это то, что вы должны делать".
Преимущество декларативного заключается в том, что вы не зацикливаетесь на деталях реализации представления государства. Вы делегируете организационную составляющую поддержания согласованности представлений вашего приложения, поэтому вам просто нужно беспокоиться о состоянии.
Представьте, что у вас есть дворецкий, который является своего рода метафорой для фреймворка. И вы хотели бы приготовить ужин. В императивном мире вы бы шаг за шагом рассказывали им, как приготовить ужин. Вы должны предоставить эти инструкции:
Go to kitchen
Open fridge
Remove chicken from fridge
...
Bring food to table
В декларативном мире вы просто опишите, что вы хотите
I want a dinner with chicken.
Если ваш дворецкий не знает, как сделать курицу, то вы не можете работать в декларативном стиле. Как если бы магистраль не знала, как мутировать себя, чтобы выполнить определенную задачу, вы не можете просто сказать ей, чтобы она выполняла эту задачу. React может быть декларативным, потому что, например, он "умеет готовить курицу". По сравнению с магистралью, которая знает только, как взаимодействовать с кухней.
Возможность описать состояние значительно уменьшает площадь поверхности для ошибок, что является преимуществом. С другой стороны, у вас может быть меньше гибкости в том, как все происходит, потому что вы делегируете или абстрагируете, как реализуете состояние.
Представьте себе простой компонент пользовательского интерфейса, например кнопку "Мне нравится". Когда вы нажимаете на нее, она становится синей, если раньше она была серой, и серой, если она была синей.
Настоятельный способ сделать это будет:
if( user.likes() ) {
if( hasBlue() ) {
removeBlue();
addGrey();
} else {
removeGrey();
addBlue();
}
}
По сути, вы должны проверить, что в данный момент находится на экране, и обработать все изменения, необходимые для его перерисовки с текущим состоянием, включая отмену изменений из предыдущего состояния. Вы можете представить, насколько это может быть сложно в реальном сценарии.
Напротив, декларативный подход будет:
if( this.state.liked ) {
return <blueLike />;
} else {
return <greyLike />;
}
Поскольку декларативный подход разделяет интересы, эта его часть должна обрабатывать только то, как пользовательский интерфейс должен выглядеть в определенном состоянии, и поэтому его гораздо проще понять.
Лучше всего сравнить React (декларативный) и JQuery (императивный), чтобы показать вам различия.
В React вам нужно только описать конечное состояние вашего пользовательского интерфейса в методе render(), не беспокоясь о том, как перейти из предыдущего состояния пользовательского интерфейса в новое состояние пользовательского интерфейса. Например, изменив текст метки с A на B.
render() {
...
<Label value={this.state.lastPrice} ... />
<Label value={this.state.askPrice} ... />
}
С другой стороны, JQuery требует от вас обязательного перехода к состоянию пользовательского интерфейса, например, выбора элемента label и обновления его текста.
update() {
...
$("#last-price-label").val(lastPrice);
$("#ask-price-label").val(askPrice);
}
В сценарии реального мира будет гораздо больше элементов пользовательского интерфейса, которые будут обновляться, а также их атрибуты (например, стили CSS и прослушиватели событий) и т. Д. Если вы сделаете это обязательно с использованием JQuery, это станет сложным и утомительным; легко забыть обновить некоторые части пользовательского интерфейса или забыть удалить старые даже прослушиватели (утечка памяти) и т. д. В этом случае происходят ошибки, т. е. состояние пользовательского интерфейса и состояние модели не синхронизированы.
Несоответствующие состояния никогда не произойдут с декларативным подходом React, потому что нам нужно только обновить состояние модели, а React отвечает за синхронизацию состояний пользовательского интерфейса и модели.
- Под крючком React обновит все измененные элементы DOM, используя императивный код.
Вы также можете прочитать мой ответ на вопрос "В чем разница между декларативным и императивным программированием?".
PS: из приведенного выше примера jQuery вы можете подумать, что если мы.введите все манипуляции с DOM в методе update() и вызываем его каждый раз, когда изменяется любое из состояний нашей модели, и мой пользовательский интерфейс никогда не будет не синхронизирован. Вы правы, и это фактически то, что делает React render(), с той лишь разницей, что jQuery update() вызовет много ненужных манипуляций с DOM, но React обновит только измененные элементы DOM, используя алгоритм Virtual DOM Diffing.
Это отличная аналогия:
* Настоятельный ответ: Выйдите из северного съезда с парковки и сверните налево. Идите на I-15 на юг, пока не дойдете до выезда на шоссе Bangerter. Сверните направо, как будто вы едете в Икею. Идите прямо и поверните направо при первом свете. Продолжить через следующий свет, затем поверните налево. Мой дом № 298.
Декларативный ответ: Мой адрес - Западный Неизменный Переулок 298, Дрейпер, Юта, 84020 *
https://tylermcginnis.com/imperative-vs-declarative-programming/
Императивный код инструктирует Javascript о том, как он должен выполнять каждый шаг. С помощью декларативного кода мы сообщаем Javascript, что мы хотим сделать, и позволяем Javascript позаботиться о выполнении шагов.
React является декларативным, потому что мы пишем нужный код, а React отвечает за принятие объявленного кода и выполнение всех шагов Javascript/DOM, чтобы получить желаемый результат.
Реальная параллель в мире императивов состояла бы в том, чтобы войти в бар для пива и дать бармену следующие инструкции: - Возьмите бокал с полки - Поставьте бокал перед разливом - Потяните вниз ручкой, пока стакан не заполнится - передай мне стакан.
Вместо этого в декларативном мире вы просто скажете: "Пиво, пожалуйста".
Декларативный подход к запросу пива предполагает, что бармен знает, как его подать, и это важный аспект работы декларативного программирования.
В декларативном программировании разработчики описывают только то, чего они хотят достичь, и нет необходимости перечислять все шаги, чтобы заставить его работать.
Тот факт, что React предлагает декларативный подход, делает его простым в использовании, и, следовательно, полученный код прост, что часто приводит к меньшему количеству ошибок и большей ремонтопригодности.
Поскольку React следует декларативной парадигме, и нет необходимости указывать ей, как взаимодействовать с DOM; Вы просто ОБЪЯВЛЯЕТЕ, что хотите видеть на экране, и React делает всю работу за вас.
Декларативное программирование - это стиль программирования, в котором приложения структурированы таким образом, что приоритет отдается описанию того, что должно происходить, а не определению того, как это должно происходить.
Чтобы понять декларативное программирование, давайте сравним его с императивным программированием (стиль программирования, который касается только того, как достичь результатов с помощью кода).
Пример: создание дружественной строки для URL. Как правило, это можно сделать, заменив все пробелы в строке дефисами, поскольку пробелы не подходят для URL. Во-первых, императивный подход к этой задаче:
const string = "difference between declarative and imperative in react.js";
const urlFriendly = "";
for (var i = 0; i < string.length; i++) {
if (string[i] === " ") {
urlFriendly += "-";
} else {
urlFriendly += string[i];
}
}
console.log(urlFriendly); // "difference-between-declarative-and-imperative-in-react-js"
В этом примере мы перебираем каждый символ в строке, заменяя пробелы по мере их появления. Структура этой программы касается только того, как такая задача может быть достигнута. Мы используем цикл for и оператор if и устанавливаем значения с помощью оператора равенства. Простой взгляд на код ничего не говорит нам, поскольку императивные программы требуют большого количества комментариев, чтобы понять, что происходит.
Теперь давайте посмотрим на декларативный подход к той же проблеме:
const string = "Difference between declarative and imperative in React.js?";
const urlFriendly = string.replace(/ /g, "-");
console.log(urlFriendly);
Здесь мы используем вместе с регулярным выражением для замены всех пробелов дефисами. С использованием
string.replace
это способ описания того, что должно произойти: необходимо заменить пробелы в строке. Детали того, как обрабатываются пробелы, абстрагируются внутри функции замены.
В декларативной программе сам синтаксис описывает, что должно произойти, а детали того, как это происходит, абстрагируются.
По сути, декларативное программирование создает приложения, о которых легче рассуждать, а когда легче рассуждать о приложении, это приложение легче масштабировать. Дополнительные сведения о парадигме декларативного программирования можно найти в по викидекларативному программированию.
Теперь рассмотрим задачу построения объектной модели документа. Императивный подход будет связан с тем, как построена DOM:
const target = document.getElementById("target");
const wrapper = document.createElement("div");
const headline = document.createElement("h1");
wrapper.id = "welcome";
headline.innerText = "Hello World";
wrapper.appendChild(headline);
target.appendChild(wrapper);
Этот код занимается созданием элементов, настройкой элементов и добавлением их в документ. Было бы очень сложно вносить изменения, добавлять функции или масштабировать 10 000 строк кода, если DOM построена императивно.
Теперь давайте посмотрим, как мы можем декларативно построить DOM с помощью компонента React:
const { render } = ReactDOM;
const Welcome = () => (
<div id="welcome">
<h1>Hello World</h1>
</div>
);
render(<Welcome />, document.getElementById("target"));
React декларативен. Здесь компонент приветствия описывает DOM, который должен быть отрисован. Функция рендеринга использует инструкции, объявленные в компоненте, для построения DOM, абстрагируясь от деталей того, как DOM должна быть отрисована. Мы ясно видим, что хотим отобразить наш компонент Welcome в элементе с идентификатором target.
Источник: Современные шаблоны для разработки приложений на React.
Декларативное программирование - это парадигма программирования... которая выражает логику вычисления без описания его потока управления.
Императивное программирование - это парадигма программирования, в которой используются операторы, изменяющие состояние программы.
ссылка: - https://codeburst.io/declarative-vs-imperative-programming-a8a7c93d9ad2
Императивный кодекс:
Когда код JavaScript написан обязательно, мы сообщаем JavaScript точно, что делать и как это сделать. Думайте об этом, как будто мы даем JavaScript-команды о том, какие именно шаги он должен предпринять.
Например, я даю вам скромный цикл:
const people = ['Amanda', 'Geoff', 'Michael', 'Richard', 'Ryan', 'Tyler']
const excitedPeople = []
for (let i = 0; i < people.length; i++) {
excitedPeople[i] = people[i] + '!'
}
Это обязательный код, хотя. Мы даем команду JavaScript, что делать на каждом этапе. Мы должны дать ему команды:
- установить начальное значение для итератора - (пусть i = 0)
- сообщить циклу for, когда он должен остановиться - (я
- получить человека в текущей позиции и добавить восклицательный знак - (people[i] + '!')
- сохранить данные в i-й позиции в другом массиве - (excitedPeople[i])
- увеличить переменную i на единицу - (i++)
Декларативный кодекс:
С помощью декларативного кода мы не кодируем все шаги, чтобы получить конечный результат. Вместо этого мы объявляем, что хотим сделать, и JavaScript позаботится об этом. Это объяснение немного абстрактно, поэтому давайте рассмотрим пример. Давайте возьмем императив для цикла кода, который мы только что рассмотрели, и реорганизовать его, чтобы сделать его более декларативным.
С помощью императивного кода мы выполняли все шаги, чтобы достичь конечного результата. Каков же конечный результат, который мы на самом деле хотим? Ну, наша отправная точка была просто массивом имен:
const people = ['Amanda', 'Geoff', 'Michael', 'Richard', 'Ryan', 'Tyler']
Конечная цель, которую мы хотим, - это массив с такими же именами, но каждое имя которого заканчивается восклицательным знаком:
["Amanda!", "Geoff!", "Michael!", "Richard!", "Ryan!", "Tyler!"]
Чтобы получить от начальной точки до конца, мы просто будем использовать функцию JavaScript.map() для объявления того, что мы хотим сделать.
const excitedPeople = people.map(name => name + '!')
Это оно! Обратите внимание, что с этим кодом у нас нет:
создал объект итератора, сообщив коду, когда он должен прекратить работу, использовал итератор для доступа к конкретному элементу в массиве людей, в котором каждая новая строка хранится в массиве excitedPeople... все эти шаги выполняются массивом JavaScript.map(). метод.
Объяснение каждого шага является обязательным подходом, например, мы должны создать тег абзаца с помощью Hello World! текст внутри.
//Imperative
const para = document.createElement('p');
para.innerText = 'Hello World !';
document.querySelector('#root').appendChild(para);
Определение желаемого конечного целевого состояния без указания точной процедуры. т.е. тег p с текстом, без указания createElement или innerText
//Delcartive
import React from "react";
import ReactDOM from "react-dom";
const App = () =>{
return(<p>Hello World !</p>);
}
ReactDOM.render(<App />, document.getElementById("root"));
Декларативное против императивного
Декларативное программирование похоже на просьбу друга нарисовать ваш дом. Вам все равно, как они его чистят, в какой цвет красят, сколько ресурсов они использовали для его завершения ».
//Declarative For Searching element from an array
array.find(item)
Противоположность декларативному - обязательна. Типичный пример императивного подхода: вы сказали другу, что именно нужно делать, чтобы покрасить свой дом.
- Помойте дом с моющим средством.
- Используйте краску Наролак или азиатскую краску.
- Покрасьте крышу в зеленый цвет.
- Получите 3 члена для заключения контракта и т. Д.
// Императивный алгоритм
def imperative_search(array, item)
for i in array do
if i == item
return item
end
end
return false
end
Итак, что же такое декларативное программирование?
Декларативное программирование — это когда более квалифицированный специалист пишет код таким образом, чтобы его поведение можно было изменить с помощью внешней конфигурации, представляющей собой ориентированный граф объектов. Например, Jetpack Compose или Flutter Widgets .
Устаревшие решения использовалиxml-like markup languages
который представлял дерево объектов пользовательского интерфейса. Например, XAML в WPF (см. FuncUI) или *.ui в Qt . У них по-прежнему есть внутренний синтаксис композиции объектов (например, DOM API), но настоятельно рекомендуется использовать язык разметки для реализации пользовательского интерфейса декларативным способом.
После того, как Facebook представил JSX, все предприятие перешло на Интернет, поскольку это дает разработчикам больше возможностей для проектирования и настройки пользовательского опыта с помощьюfunctional programming
(код существенно дешевле). В этом случае является декларативнымHTML
(ПравильнееDOM API
-> -> )
Если вы изучали информатику, вы должны знать, что все в программном обеспечении построено на абстракциях . Например в macOShardware
используетсяmach kernel
.Mach kernel
используется .Core OS
используетсяQuckTime
.QuickTime
используетсяGUI
. Как видите, субъект отношения декларативен объекту отношения.
Идея проста. ЕслиC/C++ language
носит декларативный характерassembly
, является декларативным дляC++
, является декларативным дляJavaScript
то обычно разработчики проектируют что-то, что снизит стоимость разработки приложений при использовании React (React
->Plain JS objects
->JSX
)
Сообщество придумало новый термин для определения этого явления: низкий код . Вы можете проверить исходный код этого примера приложения в этом коде или просмотреть организацию GitHub для получения дополнительных примеров.
import { Scaffold2, IScaffold2Group } from "react-declarative";
const options: IScaffold2Group[] = [
{
id: 'build',
label: 'Build',
children: [
{
id: 'authentication',
label: 'Authentication',
isVisible: async () => await ioc.authService.hasRole('unauthorized'),
icon: PeopleIcon,
tabs: [
{ id: 'tab1', label: 'Tab1 in header', },
{ id: 'tab2', label: 'Tab2 in header', },
],
options: [
{ id: 'tab1', label: 'Tab1 in side menu' },
{ id: 'tab2', label: 'Tab2 in side menu' },
],
},
{ id: 'Database', label: 'Label is optional (can be generated automatically from ID in snake case)', icon: DnsRoundedIcon, },
{ id: 'Storage', isDisabled: async () => await myAmazingGuard(), icon: PermMediaOutlinedIcon, },
{ id: 'Hosting', icon: PublicIcon, },
...
<Scaffold2
options={options}
...
PS Кроме того, декларативное программирование является более НАДЕЖНЫМ способом, потому что мы не создаем экземпляры классов GUI черезnew operator
вручную (см. Принцип инверсии зависимостей )
Это мое понимание до сих пор:
Декларативный код (почти?) Всегда является уровнем абстракции над кодом, который является более императивным по своей природе.
React позволяет писать декларативный код, который представляет собой уровень абстракции над императивным кодом, который напрямую взаимодействует с DOM (например, алгоритм сравнения ). Если вам нужно написать императивный код (т. Е. Напрямую взаимодействовать с DOM), React предоставляет ссылки в качестве аварийного выхода .
Начну с аналогии: у меня есть две машины, в моих двух машинах я хочу, чтобы температура внутри моей машины была нормальной комнатной температурой ~ 72°F. В первой (более старой) машине есть две ручки для управления температурой (1 ручка для контроля температуры и 1 ручка для управления воздушным потоком). Когда становится слишком жарко, я должен отрегулировать первую ручку, чтобы понизить температуру и, возможно, изменить поток воздуха) и наоборот, если она слишком холодная. Это обязательная работа! Я должен управлять кнопками сам. В моей второй (более новой) машине я могу установить / объявить температуру. Это означает, что мне не нужно возиться с ручками, чтобы отрегулировать температуру, которую мой автомобиль знает, я заявляю / устанавливаю ее на 72 ° F, и моя машина выполнит обязательную работу, чтобы добраться до этого состояния.
React - это то же самое, вы объявляете разметку / шаблон и стат, а затем React выполняет обязательную работу, чтобы синхронизировать DOM с вашим приложением.
<button onClick={activateTeleporter}>Activate Teleporter</button>
Вместо того, чтобы использовать .addEventListener()
чтобы настроить обработку событий, мы объявляем то, что хотим. Когда кнопка нажата, она запустит activateTeleporter
функция.
- Декларативный позволяет вам контролировать все представления. (вроде как госуправление)
- Императив позволяет вам контролировать вид. (вроде как $(это))