Глубокое слияние с AMP.setState - PullRequest
1 голос
/ 25 мая 2020

Не могу понять, как перезаписать данные через AMP.setState.

Я подготовил пример:

  • У меня есть список товаров, вывод через amp-list .
  • Каждый продукт имеет значение «количество».
  • У каждого продукта есть две кнопки: увеличить количество и уменьшить его.

<!DOCTYPE html>
<html amp lang="en">

<head>
  <meta charset="utf-8" />
  <script async src="https://cdn.ampproject.org/v0.js"></script>
  <script async custom-element="amp-list" src="https://cdn.ampproject.org/v0/amp-list-0.1.js"></script>
  <script async custom-template="amp-mustache" src="https://cdn.ampproject.org/v0/amp-mustache-0.2.js"></script>
  <script async custom-element="amp-bind" src="https://cdn.ampproject.org/v0/amp-bind-0.1.js"></script>

  <title>Hello, AMPs</title>
  <link rel="canonical" href="https://amp.dev/documentation/guides-and-tutorials/start/create/basic_markup/" />
  <meta name="viewport" content="width=device-width,minimum-scale=1,initial-scale=1" />
  <script type="application/ld+json">
    {
      "@context": "http://schema.org",
      "@type": "NewsArticle",
      "headline": "Open-source framework for publishing content",
      "datePublished": "2015-10-07T12:02:41Z",
      "image": ["logo.jpg"]
    }
  </script>
  <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>
</head>

<body>
  <amp-state id="productData" src="https://alexkazakov.info/layout/amp-edit-array-state/data.json"></amp-state>

  <h1>Welcome to the AMP web</h1>

  <amp-list height="100" items="." src="https://alexkazakov.info/layout/amp-edit-array-state/data.json" single-item [src]="productData">
    <template type="amp-mustache">
      {{#items}}
        <h3>{{name}}</h3>
        <p>Quantity: {{quantity}}</p>
        <button class="btn" on="tap:AMP.setState({productData: {items: {quantity: {{quantity}} + 1 } }})">Add +</button>
        <button class="btn" on="tap:AMP.setState({productData: {items: {quantity: {{quantity}} - 1 } }})">Reduce -</button>
        <hr />
      {{/items}}
    </template>
  </amp-list>
</body>

</html>

Здесь используется JSON:

{
  "items": [
    { "id": "0", "name": "Item 1", "price": 1.99, "quantity": 18 },
    { "id": "1", "name": "Item 2", "price": 2.99, "quantity": 15 },
    { "id": "2", "name": "Item 3", "price": 0.99, "quantity": 33 }
  ],
  "total": "9.94",
  "discount": "0%"
}

Codepen: https://codepen.io/alexandr-kazakov/pen/WNQWodZ

В моем примере я перезаписываю все значение «items», это неверно. Мне нужно, чтобы при нажатии на кнопку количество только одного товара уменьшалось или увеличивалось. Как мне это сделать?

1 Ответ

1 голос
/ 29 мая 2020

После многих часов размышлений и попыток я пришел к такому решению:

Я написал два amp-bind-macro и полностью перезаписал объект.
В amp-bind-macro я передаю индекс чтобы определить, какая кнопка была нажата. Я много искал, есть ли у l oop в amp-list встроенные индексы на каждой итерации, но я их не нашел. Мне нужно взять индексы из JSON.

Я пробовал использовать оператор распространения , но, похоже, он не поддерживается в AMP. Пришлось это сделать, но главное, что я решил свою проблему.

<!DOCTYPE html>
<html amp lang="en">
  <head>
    <meta charset="utf-8" />
    <script async src="https://cdn.ampproject.org/v0.js"></script>
    <script async custom-element="amp-list" src="https://cdn.ampproject.org/v0/amp-list-0.1.js"></script>
    <script async custom-template="amp-mustache" src="https://cdn.ampproject.org/v0/amp-mustache-0.2.js"></script>
    <script async custom-element="amp-bind" src="https://cdn.ampproject.org/v0/amp-bind-0.1.js"></script>

    <title>Hello, AMPs</title>
    <link rel="canonical" href="https://amp.dev/documentation/guides-and-tutorials/start/create/basic_markup/" />
    <meta name="viewport" content="width=device-width,minimum-scale=1,initial-scale=1" />
    <script type="application/ld+json">
      {
        "@context": "http://schema.org",
        "@type": "NewsArticle",
        "headline": "Open-source framework for publishing content",
        "datePublished": "2015-10-07T12:02:41Z",
        "image": ["logo.jpg"]
      }
    </script>
    <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>
  </head>

  <body>
    <amp-state id="productData" src="https://alexkazakov.info/layout/amp-edit-array-state/data.json"></amp-state>

    <h1>Welcome to the AMP web</h1>

    <amp-list height="100" items="." src="https://alexkazakov.info/layout/amp-edit-array-state/data.json" single-item [src]="productData">
      <template type="amp-mustache">
        {{#items}}
        <h3>{{name}}</h3>
        <p>Quantity: {{quantity}}</p>

        <amp-bind-macro id="addQuantity" arguments="argIndex" expression="productData.items.map((item, index, array) => index == argIndex ? {id: item.id, name: item.name, price: item.price, quantity: item.quantity + 1} : item )"></amp-bind-macro>
        <amp-bind-macro id="reduceQuantity" arguments="argIndex" expression="productData.items.map((item, index, array) => index == argIndex ? {id: item.id, name: item.name, price: item.price, quantity: item.quantity - 1} : item )"></amp-bind-macro>
        <button class="btn" on="tap:AMP.setState({productData: {items: addQuantity({{id}}) }})">Add +</button>
        <button class="btn" on="tap:AMP.setState({productData: {items: reduceQuantity({{id}}) }})">Reduce -</button>
        <hr />
        {{/items}}
      </template>
    </amp-list>
  </body>
</html>

Рабочая демонстрация: https://codepen.io/alexandr-kazakov/pen/ExVJQYL

...