JsRender: Новое поколение jQuery Templates

    Буквально пару месяцев назад, мы начали переписывать весьма крупный сайт, с момента прошлого крупного релиза прошёл не один год, конечно, сайт дорабатывался, правились баги и в итоге в настоящее время создаётся новая версия. В ней будет активно использоваться AJAX, поэтому весьма остро стоял вопрос с генерацией контента на клиенте, полученного в формате JSON. Прошлые шаблоны были собственной разработки, так как на то время вариантов было не так много, которые по разным причинам не подходили, базировались наши шаблоны на jquery, с помощью атрибутов происходило заполнение.

    Прежде всего было решено провести тест, при генерации списка из 1500 элементов было получено превосходство в 20 раз, похожие результаты показывает сравнение с jQuery Template (страница с тестами).

    На JsRender я вышел довольно просто. Зайдя на страницу jQuery Templates, я прочитал, что команда jQuery решила не выводить данный плагин из беты, они своё слово сдержали и уже 6 месяцев не было никаких обновлений. На этой же странице указана ссылка на блог разработчика JsRender.

    JsRender оптимизирован на высокую производительность, используются обычные строки, без взаимодействия с DOM или jQuery, что вполне логично добавляют ему производительности, так как во многих статьях о jQuery, можно встретить советы, не использовать jQuery, например, для получения id (без конструкций вида: $(this).attr('id')) и для генерации разных списков использовать только строки, после чего вставлять их в DOM одним махом.

    Рассмотрим пример с сайта:
    <html>
    <body>
    <script id="movieTemplate" type="text/x-jsrender">
    	<div>
    		{{:#index+1}}: <b>{{>name}}</b> ({{>releaseYear}})
    	</div>
    </script>
    
    <div id="movieList"></div>
    
    <script type="text/javascript">
    
    	var movies = [
    		{ name: "The Red Violin", releaseYear: "1998" },
    		{ name: "Eyes Wide Shut", releaseYear: "1999" },
    		{ name: "The Inheritance", releaseYear: "1976" }
    	];
    
    	$( "#movieList" ).html(
    		$( "#movieTemplate" ).render( movies )
    	);
    
    </script>
    </body>
    </html>
    


    В данном примере мы имеем:

    1. Шаблон (id=«movieTemplate»), неизвестный тип контента не будет обрабатываться браузером, поэтому он его рассматривает просто как текст.
    {{:#index+1}} — на вход мы подаем массив объектов, с помощью решетки мы можем получить индекс, так как он начинается с нуля, то прибавляем единицу
    {{>name}} — обращение к свойствам объекта, треугольная скобка говорит о том, что мы будем кодировать строку, т.е. будут видны теги.
    2. Контейнер, куда будет вставлен контент (id=«movieList»).
    3. Сам скрипт, где с помощью jQuery находится шаблон, происходит его заполнение с помощью render и данные вставляются в контейнер.

    После чего мы увидим такой результат:


    Основы синтаксиса в таблицах











    Пользовательские теги, вспомогательные метода и конвертеры







    Это лишь часть возможностей, в конце статьи, я приведу исчерпывающий список ссылок.

    Отладка



    Возьмём, например этот пример Helper functions. Какие-то вещи вам могут показаться не очевидными. Для своих целей я писал довольно много конвертеров и вспомогательных методов, стоит поставить точку остановки и пройтись по свойствам, многое прояснится. Я использовал Firebug, вот пример, где можно посмотреть, что содержит ссылка на объект this, которая используется в данном контексте:



    Важно



    На сайте проекта JsRender написано, что она близка к бете, разработчик обещал официальную бету в апреле или мае 2012 года на данной странице, но пока её ещё нет. Возможны изменения API, добавление новых фич и т.д. По указанной ссылке также можно задавать вопросы разработчику, судя по комментариям он довольно оперативно реагирует.

    Ссылки



    Основы JsRender (слайды): JsRender Fundamentals: Templating for HTML5 Applications
    Официальные примеры: JsRender: Demos
    Статья из двух частей: Using JsRender with JavaScript and HTML и Advanced JsRender Templating Features
    Поделиться публикацией
    Ой, у вас баннер убежал!

    Ну. И что?
    Реклама
    Комментарии 47
      +1
      Шустрее doT пока всё-равно ничего не придумали.
        0
        Насколько я вижу, то сейчас там загружена в тестах не оптимизированная версия JsRender?

        После этого инцидента:
        Revision 400: published by [jsRender won through incorrect output — removed] on 12th April 2012

        А во втором тесте у меня победу одержал: Kendo UI Templates (No «with» block)
        0
        форк DustJS от LinkedIn linkedin.github.com/dustjs/
          0
          Не нашёт сравнительных тестов…
          0
          Ага. Единственное, для поиска ошибок в шаблонах ничего не сделано.
            0
            Ну, строку, конечно, не пишет, но ошибка вполне себе нормально видна в консоли и по её тексту можно догадаться, что именно не так.
          +1
          Хорошо бы ещё написать про JsViews, вместе с которым JsRender становится действительно вкусной вещью.
            0
            С JsViews ещё не работал, дальше примеров дело не дошло, а писать о том, с чем пока не имел реальной практики я посчитал лишним. Для тех кому интересно, что такое JsViews, могут зайти на сайт и посмотреть примеры, учитывая, что JsViews базируется на основе JsRender, знакомство я бы начал с последнего.
            0
            > во многих статьях о jQuery, можно встретить советы, не использовать jQuery, например, для получения id (без конструкций вида: $(this).attr('id'))

            Не совсем так, при генерации для установки id не следует использовать $(this).attr('id', 'foo')

            > и для генерации разных списков использовать только строки, после чего вставлять их в DOM одним махом.

            Именно так. Сначала собрать всю разметку по максимуму с атрибутами, классами и идентификаторами, только потом вставить её в DOM целиком.

            А взаимодействовать с DOM всё равно придётся. Вопрос в том, сколько раз и сколько водопапов событий будет при этом спущено.
              0
              Ответил ниже.
                0
                > Не совсем так, при генерации для установки id не следует использовать $(this).attr('id', 'foo')

                Понятно, что $(this, { id: 'foo' }) проще, но в чём причина совета «не следует»?
                  0
                  Мы всё ещё о генерации говорим?

                  Не следует сначала генерировать, а потом раздавать атрибуты.
                    0
                    А как следует делать? Сразу в html собирать строку и передавать в $()?
              0
              Вы привели пример установки, а я говорил о получении.

              Вместо:
              $('a').each(function(){
                  console.log($(this).attr('id'));
              });
              


              Использовать:
              $('a').each(function(){
                  console.log(this.id);
              });
              
                –7
                вы придумали Mustache.js
                  +4
                  я придумал? я лишь рассказал о данном проекте, никакого отношения к разработке JsRender я не имею. Синтаксис с Mustache.js похож, но обозначает он разные вещи, главное что пересекается — это {{ }}.
                  0
                  Было бы полезно сравнить результаты этого движка с остальными на jsPerf.

                  Вот я когда-то сравнивал свой KiTE с другими:
                  jsperf.com/dom-vs-innerhtml-based-templating/99

                  Кстати про KiTE. У меня используется базовый mustache синтаксис расширенный if секциями.
                  Template компилируется в своеобразный bytecode — массив из строк и функций. Получается в 25 раз быстрее чем mustache. Ну и это все в 180 LOC поместилось. Надо бы глянуть во что их движок вылился в результате.
                    0
                    А есть более подробные цифры?
                    Ну например: «Ваши зубы белее на 20%», а «был цвет RAL1013, а стал RAL9003»
                      0
                      Конечно есть, на 1500 элементах тесты показали:
                      460 ms +- 10% — наши шаблоны
                      21 ms +- 10% — JsRender

                      600 элементов: 190 ms и 7 ms соответственно.

                      А тесты с jQuery Template есть во втором абзаце.
                        0
                        Ожидаемо.
                        Я недавно получил аналогичные результаты, только делал это вручную:
                        habrahabr.ru/post/147252/
                        Было
                        Views: 490.9ms | ActiveRecord: 14.4ms
                        Стало
                        Views: 12.9ms | ActiveRecord: 17.1ms
                      +3
                      Помоему сейчас столько шаблонизаторов развелось, что обсуждать преимущества одного над другим вообще смысла не имеет, мерится производительностью тоже (обычно грамотный шаблонизатор быстро работает а +- пара милисекунд не делают погоды)
                      Я даже больше скажу шаблонизаторы особо никому не нужны, обычно когда люди выбирают шаблонизатор — это знаит что на сайте мало js.
                      Если на сайте много js то люди уже выбирают средство для его структурирования, хороший фреймворк который организует код: будь то backbone или sproutcore или qooxdoo. Ну и как водится подобные рещения уже имеют свой шаблонизатор.
                      Так что дам совет тем кто выбирает шаблонизатор js:
                      1) У вам видимо небольшой сайт и не много js, 90% шаблонизаторов даже не покажут каких-либо задержек, бери любой который под рукой
                      2) У вас видимо реально большое приложение, где на основе тестов вы поняли что используемый шаблонизатор стал узким местом, тут мои советы излишни, вы сами знаете куда копать.

                      Я лично в последних проектах работал с backbone и соотвествено с шаблонизатором от underscore, тормозов не заметил, синтаксис приятен, что более нравится так там не надо заново учить новые операторы типо
                      {{for cast}}, зачем?? зачем этот синтаксис в шаблонизаторе, уже ведь есть js! поэтому в шаблонизаторе от undescore собственно три конструкции:
                      1. <%= … %> вывести значение<% … %> произвольный js<%- … %> вывести с экранированием тегов html
                        Фактически ничего не запоминаем нового и в тоже время пишем нужную логику без проблем.

                        Я не рекламирую это шаблонизатор как лучший, просто маленький пример.
                        0
                        Тоже им пользуюсь, удобно.
                        К тому же есть возможность настроить синтаксис на свой вкус.
                          0
                          Да, я активно юзал эту возможность, шаблонизатор использует стандартные теги от jsp а у меня как раз нужна была обработка этих шаблонов как jsp перед выдачей, поменял <% %> на {{ }} :)
                        0
                        Интересно было бы почитать сравнение всего многообразия строковых JS шаблонок.

                        Сам использую micro templating Резига
                          0
                          А что там справнивать, я вот лично не собо понимаю, уточните
                            0
                            Есть ли какая-то разница между ними )
                              +1
                              Не поверите!
                              1) библиотека лежащая в основе (jq template логично предположить без jq работать не будут, как и underscore)
                              2) Синтаксис
                              3)Скорость

                              Если будите выбирать то поступаем так:
                              1) Смотрим на то какая библиотека js используется в нашем проекте
                              2) Смотрим какие для этой библиотеки есть шаблонизаторы, выбираем самый приятный по синтаксису и функциям, по мне чем проще тем лучше, изучать дебри синтаксиса шаблона совсем не охота

                              Собственно все! На производительность смотреть только в том случа если они дает о себе знать ибо обычно в 97% это 5-10 шаблонов который выводят мелочь и их быстродействие ниоем образом не мешает юзеру. Вот когда вам в секунду 50 шаблонов рендерить придется тогда и задуматься стоит. А до этого ставьте на первое место удобство разработки и поддержки
                                0
                                1) библиотека лежащая в основе (jq template логично предположить без jq работать не будут, как и underscore)
                                в данном случае предположение является ложным, вот пример без зависимостей: JsRender without jQuery
                                  +2
                                  О чем предположение? Вы наверное плохо читали. я имелл виду что выбор надо основывать учитывая библиотеку лежащую в основе приложения.
                                  Используя бекбон у меня уже есть undersсore template зачем мне подключать еще один? Используя dojo у вас там тоже есть нативный шаблонизатор от dojo, у sproutcore также есть свой шаблонизатор, так зачем подключать в проект еще один?
                                  Если нет серьузной причины используйте тот шаблонизатор что уже есть, вот когда он объективно не будет устраивать стоит думать о замене
                                    0
                                    сорри, не так понял смысл коммента
                                  0
                                  А зачем подписываться на библиотеко-зависимую шаблонку?
                                    0
                                    Вы тоже коментарии не читаете? Или вы любите пложить множество непонятных библиотек чтобы потом весейлей с ними жилось?
                                    Перечитайте внимателней оба мои коментария выше.
                                      0
                                      Кладешь шаблонку без зависимостей, в чем проблема?

                                      Цель шаблонки как я её понимаю, передать нечто и получить строку готового кода, тут не нужно, с моей точки зрения никаких либ.
                                        –1
                                        Проблема в том что если функционал создания щаблонов уже заложен в библиотеку, а он заложен во многие фреймворки, подключать что-то сторонее как минимум глупо и в 99% случаем вы будити идиотом сделав это.
                                        А оставшийся 1% я ждумаю вам не встретится никогда.
                                          0
                                          Ну вот я пользуюсь jQuery, в каком месте там встроенный шаблонизатор?
                                            0
                                            Уважаемый, вы совсем дурак? Читайте мои коментарии лучше. Вы не удосужились!
                                            А речь шла о том, что если в вашем фреймворке уже есть возможность работы с шаблонами, то надо в первую очередь использовать имено её, а не подключать еще одну не понятную библиотеку.

                                            И поверьте на одной jQuery жизнь не кончается.
                                              0
                                              Вы не ответили на вопрос.
                                                0
                                                Простите но видимо вам таки не понять. Успокойтесь и делайте как знаете.
                            +1
                            Шаманство всё это. Плагин для jQuery без jQuery, под который нужно учить отдельный синтаксис.
                            Лучше Knockout-а вряд ли что-то можно придумать.
                              0
                                0
                                я бы на их месте использовал бы html5 атрибут data все таки не зра его вводят, вместо своего ng
                                  0
                                  Ну, там есть такая возможность: data-ng- вместо ng-

                                  Но сути это не меняет — Нокаут лучше из-за самого сильного механизма observables. Я могу иметь наблюдаемое проперти, которое в свою очередь возвращает в качестве значений другой наблюдаемое проперти. Причем, все они могут быть зависимыми без указания мной явных цепочек зависимостей.

                                  image

                                  Но и для многих аспектов Нокаут предоставляет гораздо более удобное и лаконичное API. Те же кастомные байндинги в Нокауте делаются одной или двумя функциями, а в angular готового рецепта нет.
                                    0
                                    В AngularJS есть $scope.$watch("variable", function() { ... }) — в общем-то те-же observerables. А вот по поводу кастомных биндингов это вы совсем зря — есть же взиожность добавления кастомынх директив, даже на главной странице есть пример (про компоненты табов). Плюс за счет тех-же директив в ангуляре легко реализуются reusable-компоненты, с которыми в knockout была беда, насколько я понял (выбирал между двумя фреймворками).
                                0
                                Соглашусь. Многие теряют из виду тот факт, что темплейты Нокаута остаются валидным HTML-кодом, а значит их может править верстальщик или дизайнер без оглядки на синтаксис разработчиков. Тем более, с учетом того, что в большинстве случаев темплейты инлайнятся в текст страницы, а не прячутся в script тагах, темплейты верстальщик может править непосредственно по готовому живому HTML прямо из браузера.
                                0

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

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