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
    30.08.2018 16:28

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

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


    1. gnaeus
      30.08.2018 17:10

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


  1. DenniLa2
    30.08.2018 16:44
    +1

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


    1. franzose
      31.08.2018 02:44

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


  1. Tantrido
    30.08.2018 17:00

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


  1. ThisMan
    30.08.2018 17:11

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


    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


    1. LoserKiss Автор
      30.08.2018 17:13

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


      1. ThisMan
        30.08.2018 17:26

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


        1. LoserKiss Автор
          30.08.2018 17:28

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


          1. dagen
            30.08.2018 23:57

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

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


            1. LoserKiss Автор
              31.08.2018 02:35

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


        1. unibasil
          31.08.2018 05:22

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


    1. LoserKiss Автор
      31.08.2018 16:35

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


  1. staticlab
    30.08.2018 18:11

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


    1. LoserKiss Автор
      30.08.2018 20:26

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


    1. DarkWanderer
      31.08.2018 11:20

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


      1. staticlab
        31.08.2018 12:05

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


        1. DarkWanderer
          31.08.2018 14:01

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

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


  1. dpr
    30.08.2018 23:06
    +1

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

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


    1. LoserKiss Автор
      31.08.2018 02:34

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