Цитата:
|
В последнее время все больше склоняюсь к выбору шаблонизатора с трансляцией на клиенте.
Кстати вот очень клевая штука: http://www.ractivejs.org/ |
Фух, почти закончил работу над новой версией, вышло дольше чем думал. На этой недели закончу, но уже предлагаю поиграться с бетой и заодно потестить : http://jsfiddle.net/NAPWB/6/.
С функциональной стороны сделано всё, что хотел, и даже больше, однако ещё нужно написать новые тесты, обновить доку и т.д. Ну а теперь по порядку. Изначально данный апдейт планировался как эволюционное развитие ветки 2.x, однако в ходе разработки, стало ясно, что необходимы некоторые принципиальные изменения, которые повлекут за собой несовместимость с предыдущей версией, поэтому новая версия выйдет как 3.0.0. Что изменилось по сравнению с 2.x: 1) Реализована блочная область видимости переменных вместо единой шаблонной, т.е. {template foo()} {if 1} {var a = 1} {a} /// 1 {/} {a} /// error, a is not defined {/} Отмечу, что данное нововведение распространяется именно на переменные, т.е. константы работают также, как и раньше. 2) Переосмыслена и переделана работа с пробельными символами: теперь любой пробельный символ (будь то табуляция или переход строки) трактуются как пробел, однако смежные пробельные символы схлопываются в один, т.е. {template foo()} /// перевод строки даст пробел <div class="foo"> {/} Также введена новая директива &, которая декларирует, что все пробельные символы после этой директивы до любого не пробельного символа будут вырезаться, т.е.: {template foo()} Привет{&} Мир! /// получится ПриветМир! {/} 3) Директивы cut и save были убраны, а их функционал частично заменила новая директива placeholder. Эта директива имеет одинаковый синтаксис с директивой template, однако, в отличии от template, placeholder существует только на этапе трансляции, т.е. {placeholder foo()} foobar {/} foo(); // error Директива может участвовать в цепи наследований также, как и template. 4) Добавлен новый возможный аргумент для директив forEach и forIn (forIn отличается от forEach тем, что всегда итерирует объект, как for (key in data), причём без проверки на hasOwnProperty). Теперь порядок аргументов для forEach такой: Для массивов: *) Ссылка на элемент массива; *) Индекс массива; *) Ссылка на итерируемый массив; *) Является ли первым; *) Является ли последним; *) Длина массива. Для объектов: *) Ссылка на свойство; *) Ключ свойства; *) Ссылка на итерируемый объект; *) Номер итерации; *) Является ли первым; *) Является ли последним; *) Длина объекта. Для forIn аргументы такие же, как и у forEach для объектов. Кстати, теперь директивы forEach и forIn разворачиваются в циклы на этапе трансляции, что позволило увеличить скорость скомпилированных шаблонов, а также возможность использования новых директив break и continue. 5) Для директивы data изменено сокращение, теперь это =, т.е. {template foo()} {= foo, bar} {/} Старое сокращение {{}} теперь используется новой директивой decl, которая вставляет текст, так как он был написан вместе со скобками директивы, т.е.: {template foo()} {{foo}} /// даст {{foo}} {/} Также, как и в data, в decl можно прокидывать переменные из шаблона, с помощью синтаксиса ${}. Новая директива decl создана для удобного использования библиотек, которые осуществляют data binding (вроде http://www.ractivejs.org/). 6) Костыль для console был удалён, теперь нужно использовать директиву void {template foo()} {void console.log(1)} /// или так {?console.log(1)} {/} На этом ломающие изменения заканчиваются. Основные нововведения: 1) Добавлена директива super, которая осуществляет вставку тела родительского блока или прототипа: {template base()} <head> {block scripts} <script src="../1.js"></script> {/} </head/> {/} {template child() extends base} {block scripts} {super} <script src="../2.js"></script> {/} {/} 2) Прототипы теперь поддерживают параметры и рекурсию, а также новую директиву return: {template foo()} {proto bar(i)} {i} {if i === 2} {return} {/} {if i} {apply bar(--i)} {/} {/} {apply bar(4)} /// 4 3 2 {/} 3) Прототипы теперь можно выносить за пределы шаблона, перед декларацией {proto foo->bar} 1 {/} {template foo()} {apply bar} {/} 4) Добавлена поддержка jsDoc /** * Данный комментарий будет в скомпилированном JS * @return {string} */ {template foo()} 1 {/} 5) Директива var теперь имеет сокращение : и поддерживает множественную декларацию {template foo()} {:a = 1} {var b = 2, e = 3} {/} 6) Новые директивы switch case (имеет сокращение >) default {template foo()} {switch 1} {case 1} foo {/} {> 2} foo2 {/} {default} foo3 {/} {/} {/} 7) Новые директивы try catch finally {template foo()} {try} {void dddd()} {catch err} {err} {finally} bar!!! {/} {/} 8) Новые директивы break и continue. Могут использоваться внутри forEach, forIn, for, while, do, repeat. 9) Для цикла repeat-until добавлен псевдоним do-while 10) Новая директива return. Может использоваться внутри прототипов или шаблона (в случае шаблона может принимать значение) 11) Новая директива attr для удобного задания атрибутов узлам в xml разметке: {template foo()} <div {attr 'class', 'foo'} {attr -'bind', 'bar'}></div> /// class="foo" data-bind="bar" {/} 12) Частично переписано АПИ добавления директив, в релизе будет иметь документацию, пример: Snakeskin.addDirective( 'if', { placement: 'template', notEmpty: true }, function (command) { this.startDir(); if (this.isSimpleOutput()) { this.save('if (' + this.prepareOutput(command, true) + ') {'); } } ); Snakeskin.addDirective( 'else', { placement: 'template' }, function () { if (this.structure.name !== 'if') { throw this.error('Directive "' + this.name + '" can only be used with a "if"'); } if (this.isSimpleOutput()) { this.save('} else {'); } } ); 13) Увеличена скорость работы транслятора и исправлено множество ошибок 14) Сильно увеличена скорость работы в "живом" режиме в браузере 15) Очень сильно доработана обработка ошибок 16) 100% code review и рефакторинг + теперь исходный код переписан на ECMAScript 6 :) Вроде всё :) |
Ради интереса сравнил скорость рендеринга с другими шаблонными движками... и каково было моё удивление, что Snakeskin занял первое место, обойдя даже самые примитивные шаблонки http://jsperf.com/templates/2 я почему то был уверен, что результат должен быть другим
|
Цитата:
Цитата:
Цитата:
Цитата:
Цитата:
Цитата:
Цитата:
Цитата:
{template} <script> .... </script> {/template}? Зачем усложнять то? Цитата:
switch text | "one" => 1 | "two" => 2 | => 0 Ну или как LiveScript: switch text case "one" then 1 case "two" then 2 case "three", "four" then "3-4" default then 0 |
Цитата:
Цитата:
Просто в современной разботке single-page приложений перерисовывать весть блок не очень гуд, особенно если в этом блоке сотни и тысячи элементов. |
Цитата:
Цитата:
|
Цитата:
Цитата:
/// Срежет не нужный пробел <p>{&} 1 2 </p> Цитата:
Цитата:
Цитата:
|
Цитата:
Если уж вводить синтаксический сахар, то лично мне кажется нужно отталкиваться от существующих решений. Вот пример из того же Haskell: f x = case x of 0 -> "one" 1 -> "two" _ -> 0 - x Цитата:
Цитата:
Цитата:
Вот к примеру в fest нет ничего лишнего, только основные инструкции и возможность писать произвольный JS код: <fest:script> var obj = {"foo": "bar"}; </fest:script> <fest:each iterate="obj" index="i"> <fest:value>obj[i]</fest:value> </fest:each> Пока я вижу в этом только плюсы, т.к. не нужно придумывать новые инструкции и усложнять парсинг. Цитата:
Цитата:
|
Цитата:
Цитата:
Цитата:
Цитата:
Цитата:
Цитата:
|
Часовой пояс GMT +3, время: 15:51. |