Как правильнее парсить результаты ajax запроса?

Есть сайт, в листинге которого с помощью ajax-запроса подгружаются данные (изначально страница генерируется не через js, а на бэкенде генерируется начальный вид страницы). Данные могут быть разных типов с разными условиями отображения.

Собственно, вопрос в том, где должно формироваться отображение данных. На выбор 2 варианта:
1) Парсить отображение на бэкенде, передавать в виде html-текста, переназначать события на новые данные.
2) Использовать шаблонизатор на js, который будет работать с данными json и брать на себя всю логику отображения.

У первого подхода я вижу следующие тонкости:
+ Вся генерация отображения расположена в одном месте, что значительно упрощает поддержку сайта в дальнейшем.
- Дольшее время подгрузки данных (на соединении 50кб/с разница между первым и вторым подходом 7 и 0,8 сек, на более высоких соединениях почти не ощущаема).
- Если подгружаемый html-текст обрастет событиями javascript, его будет сложнее поддерживать на фронте.

Второй подход показывает следующее:
+ Быстрая подгрузка данных.
+ Будет легче поддерживать события на подгружаемых объектах.
- Мы получаем 2 шаблонизатора, написанных на разных языках (один - для начальной подгрузки лент и объектов (бэкенд), второй - написанный на js для генерации логики отображения получаемых ajax-данных в json формате.
- Сложный парсинг шаблонов на js может тормозить на маломощных устройствах.

Хочу узнать о вариантах решения данного вопроса, и как обычно поступают в данных случаях? У нас все мнения поделились на 2 стороны: фронтендеры за второй вариант, а бэкендеры за первый. Может есть какое-то решение, которым будут довольны все стороны?
  • Вопрос задан
  • 3423 просмотра
Пригласить эксперта
Ответы на вопрос 2
65536
@65536
я делаю так. все состоит из блоков, где каждый блок это какое-то хтмл, к которому прилагается свой джаваскрипт, который на этот блок лично навешивает всякие обработчики. есть два случая: загрузка страницы целиком (то есть всех блоков со всеми своими джаваскриптами) и перезагрузка отдельных блоков в фоновом режиме (аджаксом так называемым). в первом случае собственно загружается страница и по готовности отрабатывают все скрипты, которые прилагаются к блокам из которых она состоит. во втором блок загружается на страницу (вставляется в нужное место, реплейсится, аппендится или еще как) и опять же отрабатывают его скрипты (именно его а не все). если в этих скриптах есть биндинги событий, то их сначала нужно отбиндить, потому что блок может перезагружаться сколько угодно раз и с каждым разом события будут навешиваться повторно и нажатие на кнопку будет слать не один запрос а столько сколько раз был перезагружен блок. никогда не было доверия ко всяким .on() .live() и тд. проще и надежнее заменить кусок кода на странице и заребиндить все что его касается.

дополнительное преимущество такое, что вся логика происходит на стороне пхп, а на стороне браузера только работа с домом, никаких вычислений, ну либо только такие, которые не будут теряться после перезагрузки блока или заставлять писать одно и то же 2 раза. только простые манипуляции и отработка событий которые будут сообщать серверу об изменениях. например, какая-нибудь форма отправки заказа, сколько ужаса я повидал, когда условия доставки рассчитываются на странице джаваскриптом а потом это отправляется на сервер (то есть я могу подменить стоимость в запросе) или на сервере подобный алгоритм считает все это еще раз чтоб типа проверить, в результате имеется зеркало алгоритма на другом языке и что-то менять нужно в 2 местах ломая голову. или жмем случайно ф5 и все слетает потому что о данных в полях кроме страницы никто не знал. как правильно в данном случае (имхо конечно же), допустим форма такая, 2 поля имя и телефон и один переключатель доставка/самовывоз. делаем для нее в сессии массив которых способен хранить состояние этих полей и переключателя, задаем дефолтные значения там же. при загрузке страницы с этой формой она просто выводится со значениями которые находятся в сессии. к ней прилагается джаваскрипт который ребиндит событие кейап на полях и событие клик на переключателе. по событию кейап отправляется значение поля чтоб сохранить его в сессии (в ответ ничего не происходит, здесь не нужно). по клику на переключателе так же шлется запрос который меняет в сессии его состояние и в ответ перезагружается вся форма (на основании актуальных данных в сессии) и все на ней заново ребиндится. не знаю смог ли объяснить, короче проще всего отправлять каждый пук пользователя на сервер, обработать его там, и перезагрузить нафиг всё на что он мог повлиять.

все эти килобайты и миллисекунды полная ерунда, все споры на эту тему это отстаивание своих знаний определенных технологий. как по мне если программа на пхп то вся логика в пхп и должна происходить а джс только обслуживать интерфейс и не более того
Ответ написан
qfox
@qfox
Ответы есть у меня
Если использовать https://github.com/bem/bh и https://github.com/bem/bh-php (шаблоны там почти 1-в-1, с точностью до $ в переменных), то можно выгружать шаблоны и на фронт, и на бекенде собирать нужное.

Еще лучше использовать прослойку на nodejs чисто для сборки html для первого захода, поисковиков, людей без JS, и не думать про это в целом, а на PHP оставить всю логику и использовать как API.

Еще, чтобы уменьшить размер передаваемых данных:
а) gzip;
б) raw-json;
в) protobuf.

Если передавать только нужное и не потеряться — нужно сделать двухпроходную шаблонизацию, т.е. в 2 шага — 1) конвертируем из сырых данных в некий промежуточный view-ориентированный json, а затем из последнего собираем html с помощью шаблонов на матчерах.

Если любите экспериметировать, можете попробовать еще вот так:
// Допустим, у нас есть выгруженные шаблоны на фронт
bh.match('users-list', function ... );
bh.match('user', function ... );
// etc.
// дальше мы должны получить данные с бекенда, для простоты укажем их явно
var usersFromBackend = [{name: 'Vasya', id: 5}, {id: 42, name: 'Petya'}, ...];
// как получили — собираем каким-то образом некую view-ориентированную структуру типа:
var viewOriented = {
  // здесь можно использовать и что-то более умное
  block : 'users-list',
  content : fromBackend.map(function (el) {
    return {
      block : 'user',
      // привязываем к users-list по БЭМ
      // (мало ли понадобится что-то в стилях-скриптах подтюнить)
      mix : { block : 'users-list', elem : 'item' }, 
      // выводим контент в каждый div
      content : {
        block : 'link',
        mix : { block : 'user', elem : 'link' },
        url : el.url || '/users/' + el.id,
        text : el.name
      }
    };
  })
};
// И после получаем готовый HTML еще одной операцией, который останется куда-то вставить
console.log(bh.apply(viewOriented));


При том, что шаблоны у нас одинаковые (для php с точностью до $ в переменных) для фронта и бекенда — кол-во дублируемого кода падает. Появляется возможность вставлять одинаковые блоки в разные места на странице с разными данными, структурировать CSS (самое известное из BEM, даже гугл рекомендует), и т.д.
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы