Прошли годы с тех пор, как вы начали использовать Redux, MobX или даже простые React Hooks и понятия не имеете, как работает управление состоянием и почему оно работает именно так? Я покажу вам крайне простой нижний уровень работы в управлении состоянием без какой-либо оптимизации или других наворотов.
Мы будем создавать глупо простую простую страницу в формате HTML с тегами сценария в ней.
Теперь давайте напишем JavaScript.
ПРИМЕЧАНИЕ. TL; DR; находится ниже ⏬
const App = function _App() { return ` <h1>Hello Vanilla JS</h1> <div>Example of state management in Vanilla JS</div> `; } document.getElementById("app").innerHTML = App();
Я мог бы просто заявить как
const App = function() {... // or const App = () => {...
Но есть причина, по которой я этого не сделал, и я объясню ее позже. Теперь давайте создадим какое-нибудь состояние
App.state = { count: 0, increment: () => { App.state.count++; } };
Простое состояние, созданное как свойство функции App
. 😉
Подождите! Вы можете сделать это? 😲
Да, все в JavaScript является объектом, и технически вы можете сделать это даже с строками и числами. Вот почему такие методы, как "hello world".toUppercase()
и (12).toFixed(2)
, будут работать. Но компилятор не позволяет вам определять свои собственные свойства для строки или числа.
Теперь, когда App
был настроен с отслеживанием состояния, мы интегрируем состояние и добавляем прослушиватель событий щелчка в конец файла.
<h1>${_App.state.count}</h1> <button id="button">Increase</button> ... document.getElementById("app").innerHTML = App(); // On Click Function document .getElementById("button") .addEventListener("click", App.state.increment);
Обратите внимание, что я получаю доступ к App
внутри себя не с помощью this
и App
, а с помощью _App
.
В имени _App
есть две особенности:
- Это позволяет функции ссылаться на себя внутри.
- Он не виден за пределами функции.
Даже если я сделаю что-то подобное ниже, код не сломается.
const Component = App; App = null; document.getElementById("app").innerHTML = Component();
Даже когда App
был переназначен на Component
, а затем стал нулевым, сама функция остается нетронутой и ссылается на себя как _App
locally, следовательно, на нее это не влияет. То же, что ‘this’ на любом другом языке программирования ООП (все мы знаем, как this
работает в JavaScript) 😅.
Теперь попробуйте запустить его (просто удвойте index.html
файл). Обратите внимание, что функция при нажатии не работает! 🙄 Это потому, что пользовательский интерфейс не отражает последнее состояние, давайте исправим это, повторно отрисовав элементы. Это можно сделать, запустив этот код еще раз при обновлении состояния.
document.getElementById("app").innerHTML = App(); // On Click Function document .getElementById("button") .addEventListener("click", App.state.increment);
Поскольку этот код есть и будет повторяться, мы извлечем его в функцию
const updateTree = () => { document.getElementById("app").innerHTML = App(); // On Click Function document .getElementById("button") .addEventListener("click", App.state.increment); }
и обновите функцию приращения как
increment: () => { App.state.count++; updateTree(); // extracted function }
Теперь наше приложение работает должным образом. И это все! это конец мертвого простого управления состоянием в ванильном JavaScript. Однако простое использование будет рассматриваться как ужасный и плохой фреймворк не из-за отсутствия каких-либо достойных функций, а из-за того, что он плохо оптимизирован, на самом деле в нем нет оптимизации, но вы уже знайте это, когда я сказал «… без какой-либо оптимизации или других наворотов» в начале этой статьи.
Список задач,
- Не следует отображать все приложение, чтобы отразить простое изменение.
- Как только мы обновим, чтобы отразить состояние, все прослушиватели событий, прикрепленные к DOM, не должны быть потеряны, и мы не должны добавлять новые прослушиватели событий вместо них.
- Элементы DOM, которые не были затронуты и не были изменены состоянием, не должны изменяться принудительно. Изменения должны быть как можно меньше
Поэтому в следующей статье мы внесем несколько оптимизаций в наше приложение, например, как это делает React и подобная библиотека / фреймворк.
TL;DR;
Вот полный HTML-файл, который мы уже закодировали.