Роутер для Matreshka.js 2

  • Tutorial

Demo
Репозиторий


tl;dr


Плагин включает синхронизацию свойств объекта и куска урла.


Matreshka.initRouter(object, '/a/b/c/');
object.a = 'foo';
object.b = 'bar';
object.c = 'baz'

// location.hash теперь #!/foo/bar/baz/

Для использования History API вместо location.hash, нужно передать строку "history" вторым аргументом.


Matreshka.initRouter(object, '/a/b/c/', 'history');

Импорт CJS модуля:


const initRouter = require('matreshka-router');
initRouter(object, '/a/b/c/', 'history');



Как работает “традиционный” роутинг? Разработчик указывает правило (роут) и описывает то, как будет себя вести приложение при соответствии урла с указанным правилом.


route('books/:id', id => {
    // делать что-то
});

Matreshka Router работает по-другому. Библиотека синхронизирует часть пути со свойством объекта.


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


Принцип работы плагина в следующем: вы указываете какая часть урла (поддерживается и hash, и HTML5 History) синхронизируется со свойством.


Скажем, вы хотите синхронизировать свойство "x" с первой частью location.hash, свойство "y" — со второй.


Matreshka.initRouter(object, "/x/y/");

Теперь когда вы пишете..


object.x = 'foo';
object.y = 'bar';

… Хеш автоматически изменится на #!/foo/bar/


И наоборот, если вы вручную, программно или с помощью стрелок “вперед” и “назад“ меняете адрес, свойства изменятся автоматически.


location.hash = '#!/baz/qux/';

// ... через несколько миллисекунд
console.log(object.x, object.y); // ‘bar’, ‘qux’

Как и всегда, свойства можно прослушивать с помощью метода on.


Matreshka.on(object, 'change:x', handler);
// или так, если объект - экземпляр Matreshka: this.on('change:x', handler);

В функцию initRouter можно передать строку со “звездочками”, для игнорирования части урла.


Matreshka.initRouter(object, '/x/*/y');

Если хеш выглядит, как #!/foo/bar/baz/, то object.x становится равным "foo", object.y"baz".


Такая возможность полезна тогда, когда один класс контролирует одну часть адреса, другой — другую.


class1.js


Matreshka.initRouter(this, '/x/*/');

class2.js


Matreshka.initRouter(this, '/*/y/');

Важно помнить две вещи:


1. Если при инициализации роутера свойство имеет правдивое значение, адрес изменится сразу после вызова initRouter. Иначе — наоборот, свойство получит значение части пути.


object.x = 'foo';

Matreshka.initRouter(object, '/x/y/');

2. Если свойство, указанное в роуте получит лживое значение, все последующие свойства, указанные в роуте, получат значение null.


Matreshka.initRouter(object, '/x/y/z/u/');

object.y = null; // установит object.z и object.u тоже в null

Идея в том, чтоб поддерживать состояния урла и свойств актуалными. Было бы странно иметь свойство "z" со значением "foo" при условии отсутствующей части адреса, связанной с этим свойством.


HTML5 History API


Кроме хеш роутинга, плагин поддерживает возможность работы с HTML5 History. Для инициализации нужно передать в метод initRoute дополнительный параметр type равный "history" (по умолчанию, type = "hash").


Matreshka.initRouter(object, '/x/y/z/', 'history');

Дополнительная информация


Ядро роутера реализовано в виде класса Matreshka.Router. Его конструктор принимает один аргумент: тип роутера ("hash", "history" или произвольную строку).


При подключении роутера создаётся два экземпляра класса Matreshka.Router с типами hash и history, которые хранятся, соответственно, в Matreshka.Router.hash и Matreshka.Router.history (используется ленивая инициализация, поэтому подключение без использования ничего не делает). Для этих двух экземпляров реализуется паттерн синглтон, т. е, при создании роутера с типом hash возвращается Matreshka.Router.hash вместо создания нового экземпляра. Такая логика централизует обработку урла, положительно влияя на производительность и не вызывает коллизии. Объекты, в свою очередь, просто подписываются на изменения и не занимаются парсингом.


"Кастомные" экземпляры Matreshka.Router могут быть созданы вручную, на случай, если нужно сгенерировать ссылку для дальнейшего произвольного использования. В этом случае, изменение свойств не повлияет на hash и не вызовет pushState.


Экземпляры класса Router имеют три свойства.


path — свойство, которое содержит актуальный урл, например, /foo/bar/baz/.


hashPath — свойство, которое сожеджит path, с дописанным к ней hashbang, например #!/foo/bar/baz/


parts — свойство, представленное в виде массива, содержащее актуальные кусочки пути, например, [‘foo’, ‘bar’, ‘baz’].


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


Matreshka.Router.hash.path = '/yo/man/';

… И два метода


subscribe(object, route) — подписывает объект на изменения в свойствах.


init() — используется для ленивой инициализации при вызове subscribe (вызывать вручную нет нужды).


const customRouter = new Matreshka.Router('myType');
const object = {
    a: 'foo',
    b: 'bar'
};

customRouter.subscribe(object, '/a/b/');

console.log(customRouter.path); // /foo/bar/

Импорт модуля CommonJS


Всё описанное выше касается немодульного окружения. Если приложение находится в окружении CommonJS (NodeJS, Webpack, Rollup...) подключение модуля matreshka-router не добавляет новых статичных свойств классу Matreshka. Вместо этого, initRouter импортируется традиционным способом.


const initRouter = require('matreshka-router');
initRouter(object, '/x/y/');

Импортировать класс Router можно так:


const Router = require('matreshka-router/router');
const customRouter = new Router('myType');

Всем добра.

  • +14
  • 10,1k
  • 1

Matreshka.js

24,68

JavaScript фреймворк для новичков

Поделиться публикацией

Похожие публикации

Комментарии 1
    +1
    Вот теперь не надо будет "колдовать"!

    Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

    Самое читаемое