Тенденция последних лет в веб-разработке — фреймворки и компиляторы (сборщики, если кому то угодно). Они везде: в javascript, css, подключаемых библиотеках и т.д. Javascript фреймворки повсеместно используют шаблоны для отрисовки всего и вся. Но у всех них есть одна общая черта — HTML. Громоздкий, свёрстанный, местами от проекта к проекту контрл+ц — контрл+в… Весь этот html всегда лежит кусками, прикрепляется конструкциями вида script type=«text/template». В общем, как будто здесь еще не придумали, как с ним бороться.
В один момент я подумал, а почему бы не перевести всю вёрстку в JSON. Он компактен, красноречив и очень хорошо читабелен (я имею ввиду сервисы а-ля jsoneditoronline.org). Порыскав готовые библиотеки понял, что эту верстку в json только усложняют и никто не сделал очевидного и простого.
И сделал — randr. Библиотечка небольшая, работает шустро.
Работает так: на вход одноимённой функции даёте определенный json, на выходе — готовый DOM (или какая-то его часть):
var json = { node: 'div', content: 'Hello World' } document.body.appendChild(randr(json));
randr из этого json`а сделает div с текстом «Hello World» внутри.
Еще можно передавать атрибуты:
var json = { node: 'div', defaults: [ { type: 'class', data: 'super-class' }, { type: 'attr', data: 'some attr value' } ], content: 'Hello World' } document.body.appendChild(randr(json));
Отлично! у нашего div`а появились атрибуты class и attr. Однажды мне finom подсказал сделать «defaults» в виде объекта со свойствами, так говорит компактнее. Сказано — сделано:
var json = { node: 'div', defaults: { class: 'super-class', attr: 'some attr value' }, content: 'Hello World' } document.body.appendChild(randr(json));
Да, стало компактнее. Оставил оба способа. Но уменьшать объем можно и другим способом. Обычно текст (в роли контента) заключен в теги «p». Именно, так мы и поступим, уберём ноду «div»:
var json = { defaults: { class: 'super-class', attr: 'some attr value' }, content: 'Hello World' } document.body.appendChild(randr(json));
Получилось! По умолчанию если отсутствует «node» а «content» является текстом — рисуем «p», иначе будет «div». Да, можно просто не писать эти пресловутые div:
var json = { defaults: { class: 'super-class', attr: 'some attr value' }, content: { content: { content: 'Хватит уже изголяться' } } } document.body.appendChild(randr(json));
Надеюсь ясно, что тут будет параграф, обёрнутый в 2 div`а. И да, контент может быть разный. Например массив:
var json = { defaults: { class: 'super-class', attr: 'some attr value' }, content: [ { content: 'параграф 1 с текстом' }, { content: 'параграф 2 с текстом' } ] document.body.appendChild(randr(json));
Вот уже лучше, но можно добавить еще кое-что! Наследование атрибутов:
var json = { defaults: { class: 'super-class', attr: 'some attr value' }, implement: true, content: [ { content: 'параграф 1 с текстом' }, { content: 'параграф 2 с текстом' } ] document.body.appendChild(randr(json));
Видно, что появился флаг implement: true — именно он отвечает за передачу атрибутов дочерним элементам. Но дети бывают капризные и не захотят принимать это наследство:
var json = { defaults: { class: 'super-class', attr: 'some attr value' }, implement: true, content: [ { content: 'параграф 1 с текстом', extend: false }, { content: 'параграф 2 с текстом' } ] document.body.appendChild(randr(json));
Думаю, тут тоже ясно. Отрицательный флаг extend не позволяет наследовать атрибуты.
Наследуются атрибуты по принципу затирания родительских дочерними, кроме стилевых классов. У них происходит склеивание — «родительский-класс дочерний-класс».
Зачем вообще наследовать их кончено каждый решит сам. Я лично использую для вспомогательных классов вроде «float-right, center, background-red». Думаю, придумать можно. Но никто не заставляет пользоваться.
Есть еще фишечка — создание своих собственных «нод». Так сказать готовых блоков хитро сверстанных элементов или просто повторяющихся заготовок:
var myNodes = { askDelete: function(content){ var container = document.createElement('div'); var bYes = document.createElement('button'); var bNo = document.createElement('button'); bYes.innerHTML = content.yes; bNo.innerHTML = content.no; container.appendChild(bYes); container.appendChild(bNo); return container; } } var json = { defaults: { class: 'super-class', attr: 'some attr value' }, content: [ { content: 'параграф 1 с текстом' }, { node: 'askDelete', content: { yes: 'Да, удалить', no: 'Нет конечно' } } ] document.body.appendChild(randr(json, myNodes));
В этом коде мы создали нашу волшебную ноду «askDelete» в объекте «myNodes» и передали объект вторым параметром в randr. А в json мы вызываем эту волшебную ноду и в качестве параметров используем свойство «content». Таким образом можно создавать свои заготовочки и внедрять их в разнообразные проекты.
Если же вам нужно получить от ranrd не DOM, а верстку в виде текста, то просто добавьте третий параметр «true» в randr:
var myNodes = { askDelete: function(content){ var container = document.createElement('div'); var bYes = document.createElement('button'); var bNo = document.createElement('button'); bYes.innerHTML = content.yes; bNo.innerHTML = content.no; container.appendChild(bYes); container.appendChild(bNo); return container; } } var json = { defaults: { class: 'super-class', attr: 'some attr value' }, content: [ { content: 'параграф 1 с текстом' }, { node: 'askDelete', content: { yes: 'Да, удалить', no: 'Нет конечно' } } ] document.body.innerHTML = randr(json, myNodes, true);
На этом всё. Думаю, такая реализация вёрстки с помощью json будет вам полезна. По крайней мере занимает меньше места и можно передавать в Ajax в виде объектов.
ссылка на оригинал статьи http://habrahabr.ru/post/260987/
Добавить комментарий