Go away HTML, go away

от автора

Тенденция последних лет в веб-разработке — фреймворки и компиляторы (сборщики, если кому то угодно). Они везде: в 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/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *