Веселый стейт менеджмент фреймворк Huex +5


image

Введение


Меня всегда удивляло, как много действий надо делать для стейт менеджмент фреймворков — сразу описывать схему, писать мутации, комитать их… Почему бы не сделать всё минимально просто?)

Зачем писать код, когда его можно не писать?

(updated)
Представляю вашему вниманию мою получасовую поделку — Huex!

Пока что решение доступно только на платформе NodeJS, но для презентации думаю будет достаточно.

Дисклеймер: Huex написан мной всего лишь в развлекательно-образовательных целях и не претендует на место полноценного фреймворка. А может и претендует. А теперь поехали.

Для чего он нужен?


Иметь единое удобное хранилище данных. Иметь возможность следить за их изменениями. Избавится он непонятных слов вроде «getters», «mutators», «actions», «commit», etc.

Как его установить?


Пока только скопировав этот репозиторий.
После того, как репозиторий скопирован, его нужно подключить через package.json вашего проекта где-то в таком виде:

"dependencies": {
    "huex": "file:../huex/"
  }

После этого он будет доступен как модуль «huex».

Или сделать еще проще, как верно заметил dpr:
npm i -S https://github.com/vssenko/huex.git

Как им пользоваться?


Максимально естественно и просто. Начнем сразу с кода:

// Подключаем huex.
const Huex = require('huex');

// Создаем хранилище.
const storage = Huex();

// Добавляем обработчики на изменение какой-либо переменной.
storage.on('change:a', (e) => console.log(`Property "a" was changed: ${e.value}`));

// Меняем значение переменной самым натуральным образом.
storage.a = 5;

И это всё. При любом изменении\установки поля нашего хранилища будут создаваться два события: change с данными { key, value } и change:key с данными { value }.
(updated)
А для вложенных объектов и массивов, события будут созданы как у вложенного объекта, так и у родителя.
Достаточно для создания проектов любой сложности.

Может что-то еще?


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

const Huex = require('huex');

const storage = Huex();

storage.a.b.c.d.e = 5;

И разумеется на все вложенные объекты так же можно навесить обработчики событий.

(updated)

Может еще что-то еще?


Да! Теперь Huex работает не только с простыми данными, но и с объектами и массивами, на ходу переделывая их в Huex-хранилища!
    sut.subSut = {
      a: 5
    };

    sut.on('change:subSut', (e) => {
      console.log(e.key); // subSut
      console.log(e.value.a) // 10
      console.log(e.nested); // { key: 'a', value: 10 }
    });

    sut.subSut.a = 10;


Еще больше примеров доступно в тестах проекта.

А в чем подвох?


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

(update)

Заключение


За два цикла (вечера) разработки у JS-сообщества появился еще один интересный фреймворк.
Что Huex умеет:
  • Инициализироваться из объекта\массива
  • Сохранять значения путем простого присваивания
  • Триггерить события при изменения себя как объекта или как массива
  • На ходу переделывать записанные в него объекты\массивы в Huex-хранилища
  • Триггерить события при изменения поля-объекта или поля-массива
  • На ходу генерировать пустые хранилища при обращении к несуществующему полю (спорная фича, но очень прикольная)

Что Huex не умеет:
  • Быть быстрым :-). Хотя, как заметил Drag13, прогресс в сторону скорости работы Proxy всё же есть, поэтому вдруг такой подход станет популярным.

Вы можете помочь и перевести немного средств на развитие сайта

Теги:



Комментарии (20):

  1. Drag13
    /#19052389

    В V8 прошлым летом прокси немного оптимизировали так что стало получше. Ну и VueJs собираются его использовать (собирались когда я последний раз смотрел)

    И да, название замечательное :)

    • gnaeus
      /#19052603

      MobX c 5 версии тоже на него перешел.

  2. DenniLa2
    /#19052477 / +1

    Huex, Huex и в продакшен ))

    • franzose
      /#19054293

      «Я поглядела, Huex у него торчит!» ©

  3. Tantrido
    /#19052557

    Как вы яхту назовёте… :)

  4. ThisMan
    /#19052609

    Не совсем понятен вот этот момент:


    if (value instanceof Object) {
      value = huex(value);
    }

    Ведь huex ни как не использует аргументы, а значит, что бы мы туда не передали, вернется все равно проксированный объект и данные потеряются


    const storage = huex();
    storage.on('change', console.log);
    storage.a = {prop: 1}; // разве тут не потеряется {prop: 1}
    storage.b = 10

    Вот что node показывает
    image

    • LoserKiss
      /#19052629

      А, это я пытался сделать так, чтобы можно было присваивать объекты и они точно так же становились Huexами, но потом на это забил, т.к. пришлось бы анализировать и вложенные объекты и т.д… Короче, есть вот такое небольшое ограничение, которое в целом можно исправить, но не нужно. Спасибо, что обратили внимание, чуть-чуть подчищу код.

      • ThisMan
        /#19052703

        А вы действительно считаете, что эта статья нужна на Хабре? Просто, сами признаете, что "проект-однодневка", "делали по фану", зачем тогда статью вообще делать? Написали бы лучше про Proxy, и как бы их можно использовать, чем делать "недо-библиотеку"

        • LoserKiss
          /#19052713

          Да, действительно так считаю. Как раз подход через использование Proxy заслуживает того, чтобы быть здесь. Статья не только «однодневка», «по фану», но еще и в какой-то степени образовательная (вот люди некоторые узнают про Proxy, посмотрят код). В конце концов, я специально написал дисклеймер, чтобы вы могли пропустить её и не тратить своё драгоценное время.

          • dagen
            /#19054065

            Не останавливайтесь на достигнутом! Вы написали Backbone.Model, но как же Backbone.View и все-все-все?

            Я о том, что каждые полгода в мире появляется по новому клону Backbone, но с использованием новых стандартов ECMAScript, самый примечательный, наверно — backbone-es6 трёхлетней давности. А ваш шуточный проект вполне может занять свою нишу в мире, если вы полностью завершите порт Backbone на новые подходы.

            • LoserKiss
              /#19054283

              Спасибо) сейчас скорее допишу для Huex возможность четкой работы с объектами и массивами)

        • unibasil
          /#19054397

          Пятница же, самое время для таких проектов и статей (пардон, это у нас на Дальнем Востоке уже пятница).

    • LoserKiss
      /#19056975

      Не думаю, что вас очень это заботит, но теперь Huex умеет отслеживать установку значений-объектов и значений-массивов :-)

  5. staticlab
    /#19052947

    "стейт менеджмент фреймворк" — это на каком языке? :)

    • LoserKiss
      /#19053373

      На языке человека со скудным словарным запасом. Руслиш :-(

    • DarkWanderer
      /#19055339

      Хмм, а расскажите пожалуйста, как это выразить на исконно-русском? Вот без всех этих тюркских, греческих, финно-угорских, французских заимствований?

      • staticlab
        /#19055569

        Не стоит бросаться из крайности в крайность и пытаться выразить всё исключительно на исконно русском. Почему бы не сформулировать как "фреймворк управления состоянием"? Или, если вам кажется, что state management лучше оставлять транслитерированным, то "фреймворк для стейт-менеджмента" будет грамматически правильнее.

        • DarkWanderer
          /#19056147

          Тем не менее часть словосочетания при любом варианте останется непереведённой, так что — по большому счёту — какая разница? Особенно в пятничной статье написанной за 30 минут (предположение)

          Собственно в своём комментарии я ставил цель проиллюстрировать, что ваша претензия выше является крайностью, как вы сами и подтвердили

  6. dpr
    /#19053953 / +1

    Пока только скопировав этот репозиторий. Я не хотел засорять npm полубессмысленными пакетами.

    Зачем же вручную копировать:
    npm i -S https://github.com/vssenko/huex.git

    • LoserKiss
      /#19054281

      Точно, забыл про это, спасибо!