Подтвердить что ты не робот

HTML-шаблон, заполненный на стороне сервера и обновленный клиентский

У меня есть веб-страница с динамическим контентом. Скажем, это страница продукта. Когда пользователь переходит непосредственно к example.com/product/123, я хочу отобразить шаблон своего продукта на сервере и отправить html в браузер. Однако, когда пользователь позже нажимает ссылку на /product/555, я бы хотел использовать JavaScript для обновления шаблона на стороне клиента.

Я хотел бы использовать что-то вроде Knockout.js или Angularjs, но я не вижу, как я могу предварительно заполнить эти шаблоны с некоторыми исходными данными на сервере и все еще иметь действующий шаблон на клиенте. т.е. если мой шаблон Angular таков:

<ul>
    <li ng-repeat="feature in features">
      {{feature.title}}
      <p>{{feature.description}}</p>
    </li>
</ul>

Когда пользователь переходит непосредственно к URL-адресу, мне нужно что-то, которое по-прежнему работает как шаблон Angular, но заполняется html для текущего продукта. Очевидно, что это не работает:

<ul>
    <li ng-repeat="feature in features">Hello
      <p>This feature was rendered server-side</p>
    </li>
    <li>Asdf <p>These are stuck here now since angular won't replace them when
       it updates.... </p></li>
</ul>

Кажется, что мой единственный вариант - отправить обработанный сервером html в браузер вместе с отдельным шаблоном соответствия...?

В этом случае я бы хотел дважды написать каждый шаблон. Это означает, что мне нужно либо переключиться на JavaScript для моего языка сервера (что мне не понравится), либо выбрать язык шаблона, который компилируется как на Java, так и на JavaScript, а затем найти способ взломать его в Play Framework (что и есть Я сейчас использую.)

Есть ли у кого-нибудь советы?

4b9b3361

Ответ 1

Если вы действительно хотите иметь начальное значение, хранящееся в области до активации Angular, вы можете использовать атрибут ng-bind, а не {{bound strings}}, из вашего примера:

<ul>
    <li ng-repeat="feature in features">
        <div ng-bind="feature.title">Hello</div>
        <p ng-bind="feature.description">This feature was rendered server-side but can be updated once angular activates</p>
    </li>
</ul>

Я не уверен, что это пригодится, но вы также захотите включить исходный набор данных как часть тега script в документе, так что, когда Angular активирует его, 'уничтожить отображаемую информацию нулями.

Изменить: (по просьбе комментаторов)

В качестве альтернативы вы можете сделать ng-repeat в верхней части списка, настроить его для заполнения на основе самого списка "features". После этого элемента ng-repeat есть элементы non-ng-repeat, у которых есть атрибут ng-hide с параметром ng-hide = "features", если Angular загружается, все элементы из исходного списка, предоставленного сервером, прячутся, и список Angular перескакивает. Никаких хакерских изменений в Angular, и не вписывается в прямой атрибут ng-bind.

В качестве дополнительной заметки вы все равно можете отправить кусок script, способный считывать этот начальный серверный элемент для своих данных, чтобы передать его в Angular до Angular, если вы хотите избежать мигания где Angular очищает данные, ожидая запроса от тех же данных с сервера.

Ответ 2

Я использовал только Knockout, но не Angular, но, по-видимому, очень распространенный подход, который я использую, заключается в том, чтобы исходное состояние ваших данных отображалось в разметке страницы как JSON, а в DOM - исходную модель представления Javascript, затем примените привязки Knockout для создания пользовательского интерфейса. Таким образом, пользовательский интерфейс формируется на стороне клиента даже для элемента, такого как ваш продукт, который уже существует на сервере. Это означает, что одни и те же шаблоны могут быть вызваны как для первоначального создания пользовательского интерфейса, так и когда вы добавляете какую-то клиентскую сторону, например, суб-продукт с его собственной моделью представления и шаблоном. Это вариант для вас?

Изменить: в случае, если я неправильно понял ваши требования, подход, о котором я говорю, подробно описан в этом вопросе: KnockoutJS дублирует данные накладные расходы

Ответ 3

Одним из вариантов в AngularJS может быть использование директивы, которая копирует значения, отображаемые на сервере, в модель и последующие действия извлекают данные через JavaScript.

Я использовал метод, описанный здесь в приложении ASP.NET WebForms, чтобы предварительно заполнить мою модель с помощью скрытых значений с сервера на первый запрос. В ходе обсуждения это прерывается с помощью Angular, но это возможно.

Вот пример html:

<input type="hidden" ng-model="modelToCopyTo" copy-to-model value='"this was set server side"' />

JavaScript:

var directiveModule = angular.module('customDirectives', []);

directiveModule.directive('copyToModel', function ($parse) {
    return function (scope, element, attrs) {
        $parse(attrs.ngModel).assign(scope, JSON.parse(attrs.value));
    }
});

Ответ 4

Я не знаю о хорошем techiqunue для этого, но это то, о чем я сейчас нахожусь в приложении rails, которое я создаю.

Вы начинаете с инициализации вашего шаблона семенными данными с помощью ng-init.

<ul ng-init="features = <%= features.to_json %>">
    <li ng-repeat="feature in features">
      {{feature.title}}
      <p>{{feature.description}}</p>
    </li>
</ul>

Затем вы дважды обрабатываете данные семени. Один раз с сервера и снова один раз Angular загрузил ваше приложение. Когда приложение загружается, Angular скроет начальные данные семени, оставив только угловой шаблон.

Важно, чтобы вы использовали ng-cloak, чтобы скрыть шаблон Angular перед его загрузкой.

<ul ng-hide="true">
  <% features.each do |feature| %>
    <li>
      <%= feature.title %>
      <p><%= feature.description =></p>
    </li>
  <% end %>
</ul>
<ul ng-hide="false" ng-cloak ng-init="features = <%= features.to_json %>">
    <li ng-repeat="feature in features">
      {{feature.title}}
      <p>{{feature.description}}</p>
    </li>
</ul>

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

В идеале я хотел бы иметь возможность повторно использовать тот же шаблон на сервере, что и на клиенте. На ум приходит что-то вроде усов. Очевидно, что трюк будет реализовывать директивы Angular и управление потоком. Нелегкая работа.