Zaawansowana interaktywność w AMP

Przyspieszone strony mobilne (AMP) to inicjatywa typu open-source, która umożliwia tworzenie szybkich i atrakcyjnych wizualnie witryn oraz reklam o dużej skuteczności.

Jeśli dopiero zaczynasz korzystać z AMP, zapoznaj się z tymi materiałami:

Motywacja

Strony AMP obsługują obszerne, dynamiczne treści z komponentami interfejsu takimi jak karuzele obrazów i reklamy lightbox. AMP obsługuje również kilka prostych sposobów, aby uruchomić jeden z komponentów za pomocą działań AMP.

Co zrobić, jeśli chcę:

  • Dostosowywanie komponentu AMP?
  • Możesz na przykład wyświetlić etykietę własną z bieżącym slajdem i łączną liczbą slajdów w karuzeli obrazów.
  • Dodać zachowań stanowych?
  • Możesz na przykład wyłączyć przycisk „Dodaj do koszyka”, jeśli dostępność produktu wybranego przez użytkownika przekracza dostępność.

Implementacja takich funkcji w AMP była trudna z powodu braku solidnego kanału komunikacji między komponentami interfejsu a braku możliwości dostosowania do wszystkich zmian stanu udostępniania. Aby rozwiązać ten problem, stworzyliśmy nowy, zaawansowany komponent AMP.

<amp-bind>

<amp-bind> to nowy komponent AMP, który umożliwia niestandardową interaktywność za pomocą wiązania danych i wyrażeń przypominających język JS. Dzięki nim dowiesz się, jak za pomocą <amp-bind> tworzyć strony AMP z interaktywną wersją niestandardową.

Co utworzysz

Z tego ćwiczenia z programowania utworzysz stronę szczegółów produktu e-commerce:

  • Używaj komponentów AMP HTML i AMP, aby tworzyć strony internetowe szybkie i zrozumiale na potrzeby użytkownika
  • Użyj <amp-bind>, aby dodać interaktywność między elementami
  • Użyj <amp-state>, aby pobrać dodatkowe dane produktów na żądanie

Czego się nauczysz:

  • Jak korzystać z wiązań danych i wyrażeń do tworzenia wspaniałych, interaktywnych stron AMP z <amp-bind>.

Czego potrzebujesz

  • Wybrana przeglądarka
  • Wybrany edytor tekstu
  • Node.js i NPM
  • Przykładowy kod
  • Podstawowa wiedza o HTML, CSS i JavaScript

Pobierz kod

Najpierw pobierz kod startowy ćwiczenia z programowania jako plik ZIP:

Pobierz

Lub przez git:

git clone https://github.com/googlecodelabs/advanced-interactivity-in-amp.git

Instalowanie zależności

W razie potrzeby rozpakuj plik archiwum i przejdź do katalogu. Zainstaluj zależności, uruchamiając npm install.

cd advanced-interactivity-in-amp-codelab
npm install

Uruchamianie serwera programistycznego

Uruchom serwer deweloperski z plikiem node.js:

node app.js

Wejdź na http://localhost:3000 w przeglądarce, by zobaczyć, jak działa strona AMP.

schemat AMP

Strona AMP to strona HTML, która ma pewne ograniczenia pod względem niezawodności. Strony AMP mają kilka specjalnych znaczników, które identyfikują je jako strony AMP w wyszukiwarce Google.

Strona AMP „Barebones” wygląda tak:

<!doctype html>
<html amp>
 <head>
   <meta charset="utf-8">
   <link rel="canonical" href="hello-world.html">
   <meta name="viewport" content="width=device-width,minimum-scale=1,initial-scale=1">
   <style amp-boilerplate>body{-webkit-animation:-amp-start 8s steps(1,end) 0s 1 normal both;-moz-animation:-amp-start 8s steps(1,end) 0s 1 normal both;-ms-animation:-amp-start 8s steps(1,end) 0s 1 normal both;animation:-amp-start 8s steps(1,end) 0s 1 normal both}@-webkit-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@-moz-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@-ms-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@-o-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}</style><noscript><style amp-boilerplate>body{-webkit-animation:none;-moz-animation:none;-ms-animation:none;animation:none}</style></noscript>
   <script async src="https://cdn.ampproject.org/v0.js"></script>
 </head>
 <body>Hello World!</body>
</html>

Komponenty AMP

Nasz kod startowy (static/index.html) tworzy stronę barbie z treścią strony (obrazami, tekstem itp.) i dodaje kilka komponentów AMP:

<script async custom-element="amp-carousel" src="https://cdn.ampproject.org/v0/amp-carousel-0.1.js"></script>
<script async custom-template="amp-mustache" src="https://cdn.ampproject.org/v0/amp-mustache-0.1.js"></script>
<script async custom-element="amp-form" src="https://cdn.ampproject.org/v0/amp-form-0.1.js"></script>
<script async custom-element="amp-selector" src="https://cdn.ampproject.org/v0/amp-selector-0.1.js"></script>

Komponenty AMP zapewniają dodatkowe funkcje i komponenty interfejsu, które wzbogacają strony AMP o elementy interaktywne. Kod początkowy zawiera te komponenty AMP:

  • <amp-carousel>
  • Karuzela obrazów, która wyświetla wiele widoków produktu.
  • <amp-mustache>
  • System szablonów służący do renderowania odpowiedzi serwera z amp-form.
  • <amp-form>
  • Dodaje specjalne funkcje do elementów <form>, które są niezbędne na stronach AMP.
  • <amp-selector>
  • semantyczny sposób wyboru jednego lub wielu elementów grupy; Może być używany jako źródło wejściowe amp-form.

Podstawowe funkcje interaktywne

Kod początkowy zawiera kilka podstawowych elementów interaktywnych:

  • Karuzela obrazów (<amp-carousel>) wyświetla wiele widoków produktu.
  • Produkt można dodać do koszyka użytkownika (przy użyciu opcji <amp-form>), klikając przycisk „Dodaj do koszyka” u dołu strony.

Spróbuj przesunąć karuzelę obrazów i dotknąć przycisku „Dodaj do koszyka”.

Ulepsz działanie

Kod początkowy ułatwia korzystanie z witryny. Możemy je ulepszyć na kilka sposobów:

  • Dodaj wskaźnik, który wyświetla obecny slajd i łączną liczbę slajdów.
  • Gdy użytkownik wybierze inny kolor koszuli, możesz zmienić karuzelę obrazów na obrazy w koszulach w tym kolorze.

Przed wprowadzeniem komponentu <amp-bind> nie można było dodawać takich funkcji. Skorzystaj z praktycznego doświadczenia z usługą <amp-bind> i dodaj te nowe funkcje do naszego przykładowego kodu.

Zainstaluj rozszerzenie <amp-bind>

<amp-bind> to nowy komponent AMP, który umożliwia niestandardową interakcję za pomocą wiązania danych i wyrażeń przypominających język JS. Aby korzystać z <amp-bind>, musisz zainstalować go na stronie.

Otwórz plik static/index.html i dodaj ten skrypt do listy komponentów AMP w sekcji <head> strony:

<script async custom-element="amp-bind"
    src="https://cdn.ampproject.org/v0/amp-bind-0.1.js"></script>

Dodawanie wskaźnika slajdu

<amp-bind> działa poprzez powiązanie atrybutów elementu z wyrażeniami niestandardowymi. Te wyrażenia mogą odwoływać się do &stanu (stanu JSON) do zmiennych. Ten stan można zainicjować za pomocą komponentu <amp-state> dołączonego do <amp-bind>.

Uruchomimy zmienną stanu, aby śledzić indeks obecnie wyświetlanego slajdu w karuzeli obrazów. Otwórz static/index.html i dodaj na górze strony <body> (przed nagłówkiem):

<amp-state id="selected">
  <script type="application/json">
    {
      "slide": 0
    }
  </script>
</amp-state>

Dane w elementach <amp-state> są dostępne przez powiązany z nimi identyfikator. Na przykład możemy odwoływać się do tej zmiennej przez ten fragment wyrażenia:

selected.slide // Evaluates to 0.

Następnie zaktualizujmy tę zmienną, gdy użytkownik zmieni slajdy w karuzeli, dodając działanie „&"” do istniejącego elementu <amp-carousel>:

<amp-carousel type="slides" layout="fixed-height" height=250 id="carousel"
    on="slideChange:AMP.setState({selected: {slide: event.index}})">

Teraz za każdym razem, gdy zmieni się wyświetlany slajd <amp-carousel>&#39, działanie AMP.setState będzie wywoływane z tym argumentem:

{
  selected: {
    slide: event.index
  }
}

Wyrażenie event.index analizuje wynik nowego indeksu slajdów, a działanie AMP.setState() scala dosłowny obiekt z bieżącym stanem. Zastępuje ona bieżącą wartość selected.slide wartością event.index.

Następnie skorzystaj z tej zmiennej stanu, która śledzi aktualnie wyświetlany slajd, i utwórz wskaźnik slajdu. Znajdź element wskaźnika slajdu (szukaj <!-- TODO: "Add a slide indicator" -->) i dodaj do elementów podrzędnych te wiązania:

<!-- TODO: "Add a slide indicator" -->
<p class="dots">
  <!-- The <span> element corresponding to the current displayed slide
       will have the 'current' CSS class. -->
  <span [class]="selected.slide == 0 ? 'current' : ''" class="current"></span>
  <span [class]="selected.slide == 1 ? 'current' : ''"></span>
  <span [class]="selected.slide == 2 ? 'current' : ''"></span>
</p>

[class] to powiązanie, które zmienia atrybut class i można go używać do dodawania lub usuwania klas CSS z dowolnego elementu.

Odśwież stronę i wypróbuj ją. Gdy zmienisz slajd w karuzeli:

  1. Wywołuje zdarzenie slideChange...
  2. Wywołanie działania AMP.setState...
  3. Aktualizuje zmienną stanu selected.slide...
  4. Aktualizuje wiązanie [class] elementu <span>.

Super! Widoczny jest również slajd.

Przydałaby się zmiana obrazów, żeby można było zobaczyć obrazy w różnych kolorach koszuli. W ten sposób można to zrobić przez powiązanie elementu [src] z elementami <amp-img> w obrębie <amp-carousel>.

Najpierw jednak musimy zainicjować dane stanu za pomocą źródłowych adresów URL obrazów dla każdej kolorowej koszuli. Zróbmy to z nowym elementem <amp-state>:

<!-- Available shirts. Maps unique string identifier to color and image URL string. -->
<amp-state id="shirts">
  <script type="application/json">
    {
      "1001": {
        "color": "black",
        "image": "./shirts/black.jpg"
      },
      "1002": {
        "color": "blue",
        "image": "./shirts/blue.jpg"
      },
      "1010": {
        "color": "brown",
        "image": "./shirts/brown.jpg"
      },
      "1014": {
        "color": "dark green",
        "image": "./shirts/dark-green.jpg"
      },
      "1015": {
        "color": "gray",
        "image": "./shirts/gray.jpg"
      },
      "1016": {
        "color": "light gray",
        "image": "./shirts/light-gray.jpg"
      },
      "1021": {
        "color": "navy",
        "image": "./shirts/navy.jpg"
      },
      "1030": {
        "color": "wine",
        "image": "./shirts/wine.jpg"
      }
    }
  </script>
</amp-state>

Ten element <amp-state> zawiera obiekt JSON, który mapuje ciąg identyfikatora koszulki (np. kod SKU) na kolor i adres URL zdjęcia odpowiedniej koszuli. Także tablica JSON będzie działać, ale użycie obiektu pozwala nam robić więcej fajnych rzeczy, które wkrótce zobaczysz.

Teraz możemy uzyskać dostęp do adresu URL zdjęcia za pomocą identyfikatora koszulki. Na przykład shirts['10014'].color zwraca wartość "dark green", a shirts['10030'].image zwraca URL obrazu dla koloru koszulki „wine&quot”.

Jeśli dodamy kolejną zmienną stan śledzącą wybrany kod SKU, możemy powiązać wyrażenie z elementami <amp-img>, aby zaktualizować ich atrybuty src po każdej zmianie wybranego kodu SKU. Dodaj nowy klucz sku do istniejącego elementu amp-state#selected w elemencie JSON:

<amp-state id="selected">
  <script type="application/json">
    {
      "slide": 0,
      "sku": "1001"
    }
  </script>
</amp-state>

Dodaj „&"” do elementu <amp-selector>, który aktualizuje zmienną selected.sku po wybraniu nowego koloru:

<amp-selector name="color" 
    on="select:AMP.setState({selected: {sku: event.targetOption}})">

Następnie dodaj wiązania do elementów <amp-img> w elemencie <amp-carousel> (szukaj <!-- TODO: "Changing images in amp-carousel-->"):

<!-- Update the `src` of each <amp-img> when the `selected.sku` variable changes. -->
<amp-img width=200 height=250 src="./shirts/black.jpg"
    [src]="shirts[selected.sku].image"></amp-img>
<amp-img width=300 height=375 src="./shirts/black.jpg"
    [src]="shirts[selected.sku].image"></amp-img>
<amp-img width=400 height=500 src="./shirts/black.jpg"
    [src]="shirts[selected.sku].image"></amp-img>

Uwaga: w praktyce każdy obraz w karuzeli prawdopodobnie będzie miał inny src. Można to zrobić, zamieniając jeden obraz na szereg obrazów. Dla uproszczenia w tym ćwiczeniu z programowania wykorzystaliśmy 1 obraz o różnych powiększeniach.

Teraz odśwież stronę i wybierz inny kolor koszulki. Gdy tak zrobisz, obrazy w karuzeli zostaną zaktualizowane, by wyświetlać koszule w wybranym kolorze.

Co w sytuacji, gdy dane, które można powiązać, są zbyt duże lub złożone, aby można je było pobrać podczas wczytywania strony? A jeśli każda jednostka SKU ma cenę, której znalezienie zajmuje dużo czasu? Wyszukiwanie cen kodów SKU niewyświetlonych produktów jest niepotrzebne.

Pobieranie dostępnych rozmiarów koszulki

Skorzystaj z możliwości pobierania danych zdalnych w celu wyszukiwania cen w kodach SKU w naszym przykładzie. Nasz serwer programisty Express.js w app.js zawiera już punkt końcowy /shirts/sizes?shirt=<sku>, który zgodnie z kodem SKU koszulki zwraca dostępne rozmiary i ceny dla poszczególnych rozmiarów. Wysyła odpowiedź z sztucznym opóźnieniem wynoszącym 1 sekundę, aby symulować opóźnienie sieciowe.

Wyślij

Odpowiedź

GET /shirts/sizesAndPrices?sku=1001

{"1001: {"sizes": {"XS": 8.99, "S" 9.99}}}

Podobnie jak w przypadku danych JSON w elementach <amp-state> dane zdalne zwrócone z tych pobrań są łączone i dostępne w atrybucie id elementu. Na przykład dane zwrócone w przykładowej odpowiedzi można wyświetlić w wyrażeniu:

Wyrażenie

Wyniki

shirts['1001'].sizes['XS']

8.99

Teraz zastosujemy to do naszego przykładu e-commerce. Najpierw pobierz dane tej koszulki po wybraniu nowego kodu SKU. Dodaj wiązanie [src] do elementu amp-state#shirts:

<!-- When `selected.sku` changes, update the `src` attribute and fetch
     JSON at the new URL. Then, merge that data under `id` ("shirts"). -->
<amp-state id="shirts" [src]="'/shirts/sizesAndPrices?sku=' + selected.sku">

Teraz wyraźnie odznaczymy niedostępne rozmiary jako dotyczące danego kodu SKU. Klasa CSS "unavailable" dodaje przekątną przez element. Możemy dodać ją do elementów w elemencie amp-selector[name="size"] odpowiadającym niedostępnym rozmiarom:

<amp-selector name="size">
  <table>
    <tr>
      <!-- If 'XS' size is available for selected SKU, return empty string.
           Otherwise, return 'unavailable'. -->
      <td [class]="shirts[selected.sku].sizes['XS'] ? '' : 'unavailable'">
        <div option="XS">XS</div>
      </td>
      <td [class]="shirts[selected.sku].sizes['S'] ? '' : 'unavailable'">
        <div option="S">S</div>
      </td>
      <td [class]="shirts[selected.sku].sizes['M'] ? '' : 'unavailable'">
        <div option="M">M</div>
      </td>
      <td [class]="shirts[selected.sku].sizes['L'] ? '' : 'unavailable'">
        <div option="L">L</div>
      </td>
      <td [class]="shirts[selected.sku].sizes['XL'] ? '' : 'unavailable'">
        <div option="XL">XL</div>
      </td>
    </tr>
  </table>
</amp-selector>

Załaduj ponownie stronę i wypróbuj ją. Wybór nowego kodu SKU (kolor koszulki) spowoduje przekreślenie niedostępnych rozmiarów (z krótkim opóźnieniem).

Jest jednak mały problem – co z czarną koszulą, domyślnie wybranym kolorem? Będziemy musieli dodać rozmiar i cenę czarnej koszulki do: amp-state#shirts...

<amp-state id="shirts" [src]="'/shirts/sizesAndPrices?sku=' + selected.sku">
  <script type="application/json">
    {
      "1001": {
        "color": "black",
        "image": "./shirts/black.jpg",
        "sizes": {
          "XS": 8.99,
          "S": 9.99
        }
      },
<!-- ... -->

...oraz aktualizować domyślny stan odpowiednich elementów.

<amp-selector name="size">
  <table>
    <tr>
      <!-- If 'XS' size is available for selected SKU, return empty string.
           Otherwise, return 'unavailable'. -->
      <td [class]="shirts[selected.sku].sizes['XS'] ? '' : 'unavailable'">
        <div option="XS">XS</div>
      </td>
      <td [class]="shirts[selected.sku].sizes['S'] ? '' : 'unavailable'">
        <div option="S">S</div>
      </td>
      <!-- Add the ‘unavailable' class to the next three <td> elements
           to be consistent with the available sizes of the default SKU. -->
      <td class="unavailable" 
          [class]="shirts[selected.sku].sizes['M'] ? '' : 'unavailable'">
        <div option="M">M</div>
      </td>
      <td class="unavailable" 
          [class]="shirts[selected.sku].sizes['L'] ? '' : 'unavailable'">
        <div option="L">L</div>
      </td>
      <td class="unavailable" 
          [class]="shirts[selected.sku].sizes['XL'] ? '' : 'unavailable'">
        <div option="XL">XL</div>
      </td>
    </tr>
  </table>
</amp-selector>

Zmienne ceny koszulki

Teraz gdy prawidłowo wyświetlamy dostępne rozmiary, sprawdź, czy również wyświetlana jest prawidłowa cena.

Nasz sklep AMPPAREL jest specyficzny, ponieważ cena koszulki zależy od koloru i rozmiaru. To oznacza, że do śledzenia rozmiaru wybranego przez użytkownika potrzebujemy nowej zmiennej. Dodaj nowe działanie do elementu <amp-selector> o rozmiarze:

<!-- When an element is selected, set the `selectedSize` variable to the
     value of the "option" attribute of the selected element.  -->
<amp-selector name="size" 
    on="select:AMP.setState({selectedSize: event.targetOption})">

Pamiętaj, że nie inicjujemy wartości elementu selectedSize za pomocą elementu amp-state#selected. Wynika to z tego, że celowo nie podajemy domyślnego wybranego rozmiaru i chcemy wymusić na użytkowniku wybór rozmiaru.

Dodaj nowy element <span> z etykietą ceny i zmień tekst domyślny na „"---"”, ponieważ nie wybrano żadnego domyślnego rozmiaru.

<h6>PRICE :
  <!-- Display the price of the selected shirt in the selected size if available.
       Otherwise, display the placeholder text '---'. -->
  <span [text]="shirts[selected.sku].sizes[selectedSize] || '---'">---</span>
</h6>

A my mamy poprawne ceny. Wypróbuj tę funkcję.

Przycisk włączony warunkowo

Prawie gotowe! Teraz wyłączmy przycisk „Dodaj do koszyka”, gdy wybrany rozmiar jest niedostępny:

<!-- Disable the "ADD TO CART" button when:
     1. There is no selected size, OR
     2. The available sizes for the selected SKU haven't been fetched yet
-->
<input type="submit" value="ADD TO CART" disabled
    class="mdl-button mdl-button--raised mdl-button--accent"
    [disabled]="!selectedSize || !shirts[selected.sku].sizes[selectedSize]">

Udostępniamy interaktywną stronę z informacjami o produkcie dla sklepów internetowych z różnymi rozmiarami i cenami dla poszczególnych kodów SKU, pobierana na żądanie ze zdalnego punktu końcowego JSON.

Jeśli nie wiesz, co zrobić, zajrzyj na stronę static/final.html.

Mamy nadzieję, że te ćwiczenia z programowania okażą się przydatne przy tworzeniu elastycznych stron AMP za pomocą znaczników <amp-bind>. Więcej informacji znajdziesz w dokumentacji &amp-bind>.

Zachęcamy do otrzymywania opinii – prześlij nam swoje propozycje funkcji, sugestie lub zgłoszenia błędów. Jeśli chcesz przetestować działanie aplikacji <amp-bind> z udziałem prawdziwych użytkowników, rozważ skorzystanie z wersji próbnej.

Już wkrótce uruchomimy usługę <amp-bind> i zobaczymy, co możesz z niego zrobić.