Прошли годы с тех пор, как вы начали использовать 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 есть две особенности:

  1. Это позволяет функции ссылаться на себя внутри.
  2. Он не виден за пределами функции.

Даже если я сделаю что-то подобное ниже, код не сломается.

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-файл, который мы уже закодировали.