Pull to refresh

Comments 56

Да, пожалуй, интересный движок. Но он занимает 9кб в сжатом виде
Ваш — 4, тот — 9, разница явно не на порядок :-)
Хорошо, 2. И тот и другой загрузятся менее, чем за секунду. Имхо, в этом конкретном случае размер не имеет значения. Для кого-то Ваш движок лучше, для кого-то — jtemplates, я дал ссылку, чтобы была свобода выбора, т.к. Вы его в списке не указали :-)
вообще-то значимой границей является 200мс.
вообще-то все эти числа вывосаны из пальца
Шаблонизатор шаблонизатора. Надо написать jQuery templates templates.
Я понимаю что такие вопросы редко задают с реальным интересом и их сразу заминусовывают, однако мне правда интересно: зачем? В чём выгода темплейтов на jQuery?
Какие отличия между jQ-темплейтами и темплйтами на джанго, мако или генши, помимо того что темплейты рендерятся на клиенте? Как быстро оно работает? Как быстро оно будет работать с темплейтом страницы хабра(чисто прикинуть если все поля)?
На мой взгляд, в основном выгода идет на страницах с динамически добавляемым контентом, как, например, комментарии на хабрахабре.
Скорость же работы движка довольно быстрая. Основное время выполнения занимает компиляция в байт-код функции шаблона. То есть, если не генерировать новые шаблоны в большом количестве, все будет работать быстро.
Т.е. вы хотите сказать что необходимо подгружать страницу сразу со всеми или почти всеми темплейтами на jQ, при этом рендерить их в DOM при получении информации через AJAX?
Да, интересный подход. Однако, на сколько оно удобно используется?
Ваша мысль интересна, однако хотелось бы узнать зачем оно создавалось.
В случае же с вашей идеей, придётся ли хранить все темплейты в памяти? Будут ли проблемы с памятью? Нет, я не скряга, который экономит на битах, но не хочется чтобы при загрузке страниц 15 браузер(IE, FF, как минимум) напрягался. А ещё и флеш ведь…
Писали мы как-то проект по поиску в частных объявлениях. Конечно, сразу оговаривалось, что должен быть AJAX, однако даже с AJAX поначалу тормозило (каждая страница в результатах, каждое изменение фильтра и т.д. — запрос на сервер), а так как мы не Гугл (в смысле серверной мощи), то было принято решение использовать связку TaffyDb+jQuery templates. Получилось очень даже шустро. То есть примитивно алгоритм был таков:

  1. Делаем запрос на сервер без параметров фильтра — только сам запрос. Например, «mazda CX-7»
  2. Получаем сразу все данные в JSON и сохраняем в TaffyDb
  3. Выводим и фильтруем данные не на сервере, а прямо на клиенте


Какие профиты?
  1. Скорость увеличивается до скорости десктопного приложения
  2. Нагрузка переносится с сервера на клиента. Фактически сервер только парсит объявления, сохраняет их в базу и возвращает по запросам (без просеивания, упорядочивания и пр. действий)

Такого ответа и ждал, а конкретно на счёт способа хранения сериализированного ответа от сервера.
А вы прямо _весь_ результат сохраняете или есть какое-то ограничение? А то вот придёт мегабайт 10 результатов и всё, крендец. Или нет?
Я сейчас занимаюсь одним проектом, где могу допустить свободу выбора в смысле инновационных «фич» вроде jQ-темплейтов и полного перенесения всей клиентской части на клиента, вот хочется подробнее узнать.
Ну, у нас там было ограничение на 200 результатов. Но если бы этого ограничения бы не было, мы бы грузили данные поэтапно, в фоновом режиме. TaffyDb работает просто как Javascript массив, потому объем хранилища ограничен только объемом оперативной памяти.
а на сколько в таком случае будет тормозить клиент, если ему кусками скормить несколько мегабайт данных??
я думаю, что даже задача пейджинга с сортировкой на 500+страниц и 20-ю анонасами/стр. уже будет сильно грузить клиент.
Не знаю, не пробовал. Но вы мне скажите, пользователь сможет просмотреть сразу 500 страниц? Нет. Если это поиск, то он 2-4 страницы посмотрит и бросит это дело.

Я бы для 500 страниц делал бы так: постоянно в памяти держать страницы 1-10 и с текущей стр. -10 до текущей страницы+10. Ну и последние 10. И подгружал бы новые данные по мере навигации пользователя, а остальные уничтожал бы.
с этим понятно. вопрос был касательно использования для пейджинга, ведь если сделать сортировку по имени, то придется делать новый запрос.
В целом мне интересно узнать о реальных применениях как самих шаблонов так и «БД». Если эту тему где то поднимали, буду признателен на ссылку.
Если хранить данные на клиенте целиком, то сортировка выполняется тоже на клиенте. А если подгружать с сервера, тогда — да, придется повторять запросы.

Я вижу выход только в одном — минимизации объема данных, передаваемых с сервера. Например, если надо показывать картинку, то сделать так, чтобы ее путь можно было генерировать из оставшихся данных (например, по id) и т.д.

Касательно ссылок:

Группа TaffyDB на Yahoo: tech.groups.yahoo.com/group/taffydb/
Tutorial по написанию компонента типа grid: taffydb.com/Javascript_table_grid_application.htm (информация весьма устарела, но в качестве основы — пойдет)
TaffyDb и jLinq: goo.gl/7Wcd
Это круто на самом деле, если учесть, что контента довольно много.
Тоже как-то раз озадачился JS темплейт-движком. На мой взгляд, единственным нормальным из существующих решений является Pure — потому как здесь уже нужна не «генерация строк», а генерация объектов, со всеми вытекающими типа навешивания эвент хэндлеров на сгенерированные объекты без беганья по дому и прочим. Но автор Pure чего-то покурил и сделал из хорошей штуки какого-то монстра, с блекджеком и своими селекторами, буээ.
Позже возможно напишу ещё на эту тему ; )
Объясните, пожалуйста, где применяется данный шаблонизатор.
Эти проекты еще в разработке, написал я его недавно.
UFO just landed and posted this here
Вот, +1 к jTemplates.

Расскажу о реальном применении.

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

Как поступать?

Генерировать html на сервере в корне неверно, т.к. не разделяются данные и представление.

Писать что-то вроде "" + id + '<a href="'+… тоже неправильно.

Тут на помощь приходят шаблоны.

Они чем-то похожи на View из MVC.

Черт, отправился случайно комментарий.

Дополнение:

Итого, логика такая:
— все данные хранятся в массиве объектов, который уже сформирован и передан клиенту
— при перетаскивании и дропе идет выборка данных из этого массива (по некоторым причинам не используется аякс при каждом
действии, но принцип тот же), формируется объект с необходимыми данными, и добавляется в другой массив,
с выбранными объектами
— данные из объекта подставляются в шаблон и движок jTemplates рендерит этот шаблон в DOM

Т.е. работа с данными и работа с отображением полностью отделена.

Этот подход, как выше писал donnerjack13589, полностью оправдан в случае с динамическим содержимым,
все отображение отдано клиенту, сервер генерирует только данные.
Указывал в начале статьи, но есть некоторые ограничения, которые мой шаблонизатор может обойти. Например проблему «undefined variable», которая возникает с использованием «with(..) {..}»
У большинства из описанных движков, на мой взгляд, есть серьёзные недостатки: отсутствие вменяемого механизма сообщения об ошибках (как компиляции так и выполнения) в шаблоне и встроенной поддержки экранирования выводимых значений.

Для сравнения, вот наш вариант шаблонизатора (public domain), документация внутри.

Кроме того, есть ещё вопрос производительности. Большинство шаблонизаторов работают со сравнимой скоростью, но есть некоторые (напр. Tempest, Nano и jQuery template plugin) в которых нет встроенной поддержки циклов, и они дико (примерно на порядок) тормознутее других при выводе данных в цикле.
Во-первых:
var POWER; POWER = POWER || {};
То же самое, что:
var POWER = POWER || {};.

Во-вторых:
Насчет скорости работы.
Вы каждую строчку текста пропускаете через функцию, в которой выполняется 5 раз split и 5 раз join.
Каждую строчку кода через 2 replace с регулярным выражением.

И еще, ведете replace по сложному регулярному выражению. А замена идет через функцию с 4мя if'ами, большая часть которых кодирует в вид «p.push(...)».
Добавление в массив через push очень неэффективно.

Плюс, невозможность расширения без правки исходника.

И еще весь код шаблона помещен в блок try — catch, что заметно понижает скорость работы.

И еще одно, я проводил тесты и писал версию своего движка, с использованием replace функции вместо split и join(она есть на google code).

Так вот, скорость работы такой версии ниже, чем split&join.
Насчёт var POWER = — можно и var не писать, смысл останется тот же. Проблема в том, что кто-то на такие сокращённые конструкции ругается, уже не помню, кто именно.

Насчёт скорости. Скорость важна, но отсутствие дыр в безопасности ещё важнее: выводимые данные обязательно надо экранировать, за редкими исключениями (для которых в моём движке есть <%# ... %>). И если для этого надо прогнать 5 split-join-ов, значит так надо и оптимизировать здесь нечего.
Что касается 2-х replace, то я не совсем понял, о чём речь — если Вы про encodeJS, то первый replace заменить на split+join невозможно, а замена второго большой оптимизации не даст.

Я тоже скорость replace vs split+join менял, split+join быстрее. Но я так же мерял скорость всех этих движков — мой в первой тройке (самый шустрый Underscore), и разница между практически всеми движками незначительная (кроме тех, которые не поддерживают циклы). Для тестирования взял тесты Brian Landau из git-репозитория плюс немного пропатчил их для удобства, чтобы тесты запускались при входе на страничку а не из консоли ручками.

try-catch необходим для обнаружения и вывода сообщений об ошибках в шаблонах, с номерами строк и контекстом. Отсутствие этой фичи у других было одной из основных причин писать свой движок.

Остальные replace-ы и if-ы для увеличения читабельности и упрощения расширения движка. Тем более, что оптимизировать этот код причин нет, согласно проведённым бенчмаркам. Возможность расширения движка на лету без модификации кода с моей точки зрения — недостаток, т.к. избыточно увеличивает гибкость и затрудняет понимание кода если этой фичей будут пользоваться (аналогично перегрузке операторов в некоторых языках).
Если var не написать, получится глобальная переменная; смысл совсем не останется тот же.
Дык она и так глобальная. Почитайте, как работает var.
Ну давайте на счет тестов. Я посмотрел тот тест.
В чем смысл запускать один и тот же шаблон столько раз?
В моем шаблонизаторе он с первого же раза за кэшируется и скорость работы будет почти мгновенная.
Имеют смысл только benchmark с изменяющимся шаблоном.

Насчет экранирования, я не считаю это довольно часто практикой, поэтому убрал эту функцию из ядра (хотя, возможно и стоит ее туда вернуть). В любом случае вы можете расширить мой движок модификаторами.

Сейчас проведу тесты вашего и моего движка и выложу результаты.
Ладно, признаю, в моем коде была ошибка и в результате шабоны не кэшировались.
Я сейчас поправил и выложил новую версию и benchmark test: dev.habrastat.ru/jquery.tpl/test/

Вот результаты на моей машине:
jQuery.tpl different:
1040 ms — 100 iterations (4200 max length of tpl)
2837 ms — 200 iterations (8400 max length of tpl)
4745 ms — 300 iterations (12600 max length of tpl)
7094 ms — 400 iterations (16800 max length of tpl)
9575 ms — 500 iterations (21000 max length of tpl)
jQuery.tpl similar:
290 ms — 100 iterations
554 ms — 200 iterations
937 ms — 300 iterations
1174 ms — 400 iterations
1450 ms — 500 iterations
POWER different:
1472 ms — 100 iterations (4200 max length of tpl)
3868 ms — 200 iterations (8400 max length of tpl)
8658 ms — 300 iterations (12600 max length of tpl)
14823 ms — 400 iterations (16800 max length of tpl)
23040 ms — 500 iterations (21000 max length of tpl)
POWER similar:
603 ms — 100 iterations
1051 ms — 200 iterations
1601 ms — 300 iterations
2740 ms — 400 iterations
4180 ms — 500 iterations

Как видно, мой шаблонизатор быстрее вашего.
Извиняюсь, я немного преукрасил действительность (передавал в ваш скрипт $sim[0] вместо $sim[1]).

Вот это ближе к реальности:
jQuery.tpl different:
928 ms — 100 iterations (4200 max length of tpl)
2376 ms — 200 iterations (8400 max length of tpl)
4125 ms — 300 iterations (12600 max length of tpl)
6578 ms — 400 iterations (16800 max length of tpl)
9010 ms — 500 iterations (21000 max length of tpl)
jQuery.tpl similar:
272 ms — 100 iterations
596 ms — 200 iterations
779 ms — 300 iterations
1038 ms — 400 iterations
1295 ms — 500 iterations
POWER different:
1023 ms — 100 iterations (4200 max length of tpl)
4540 ms — 200 iterations (8400 max length of tpl)
7511 ms — 300 iterations (12600 max length of tpl)
13759 ms — 400 iterations (16800 max length of tpl)
20731 ms — 500 iterations (21000 max length of tpl)
POWER similar:
2063 ms — 100 iterations
3398 ms — 200 iterations
5160 ms — 300 iterations
7522 ms — 400 iterations
8846 ms — 500 iterations
Я пришёл к выводу, что тут лучше велосипед, чем что-то стороннее. Быстрее, проще, намного проще и быстрее.

var Template = T = function(source) { this.source = source; }

Template.prototype = {
    source: '',
    apply: function(config) {
        config = config || {};
        return this.source.replace(/{{\s*(.*?)\s*}}/g,
            function (a, b) {
                var r = config[b];
                if (typeof r == "undefined")
                    r = "";
                return r;
            }
        );
    }
}

// Применение
var t = new T('<li class="mylist"><a href="{{ url }}"><span>{{ url }} - {{ title }}</a></li>');
for (var i=10; i; i--)
    $('ul').append(t.apply({ url: 'http://ya.ru', title: 'Ya.ru' }))


* This source code was highlighted with Source Code Highlighter.

Вы правы, примерно так и работает Nano. Но иногда все-таки нужны циклы и возможность навешать события.
я бы не стал называть метод apply. Ну мало ли, нативный apply понадобится…
Это же метод объекта с прототипом Template, а не Function. Нативный метод остается нетронутым
var MyObject = function(a){this.a = a;}
MyObject.prototype = {
a: ''
}

var MyObj_2 = {};
MyObject.apply(MyObj_2, [2]);

console.log(MyObj_2.a);

Все объекты это наследники Function.
А я разве спорю? Да, коструктор. Но побочный эффект этого факта в том, что объект наследует все члены Function. В частности метод apply. Который я и не советовал переопределять на случай «мало ли чего».
Я пользуюсь шаблонизатором из Underscore JS — он сделан на базе шаблонизатора Рейсига и чертовски удобен для Rails программеров.
Уже давно изобретенный велосипед Ext.Template. Можно и трех колесный вариант Ext.XTemplate но это уже не по MIT лицензии.

Мне кажется сомнительным включение шаблонов в jQuery core, но что то стандартизованное для плагинописателей было бы здорово.
Я как-то искал движок, работающий и на клиенте, и на сервере (.net в моем случае). Ну, т.е. чтобы можно было, например, куски страницы делать динамическими без переписывания шаблонов. Или чтобы изначальный вариант отрендерить на сервере, а потом обновлять на клиенте.

Под .net что-то подобное можно сделать на django templates. Реализации — dojo.dtl и nDjango соответственно. Оба — сыроваты.
Самое лучшее решение, которое я когда-либо встречал для jQuery — это TrimPath JST
Sign up to leave a comment.

Articles