AMP

处理远程数据

如果你的可绑定数据太大或太复杂,无法在页面加载时检索怎么办?或者如果每个 SKU 都有一个价格,需要很长时间才能查找怎么办?查找未查看商品的 SKU 的价格是浪费工作。

<amp-state> 支持通过其 src 属性获取远程数据,该属性从 CORS 端点获取 JSON。此获取操作在页面加载时执行一次,对于确保数据的新鲜度很有用(尤其是在从缓存中提供时)。

你还可以绑定 <amp-state> 元素的 src 属性。这意味着用户操作可以触发将远程 JSON 数据获取到页面的可绑定状态中。

获取衬衫的可用尺码

让我们利用获取远程数据的能力来查找示例中 SKU 的价格。我们在 app.js 中的 Express.js 开发服务器已经有一个端点 /shirts/sizesAndPrices?shirt=<sku>,给定一个衬衫 SKU,它会返回每个尺码的可用尺码和价格。它会发送响应,并人为地延迟一秒钟以模拟网络延迟。

请求 响应
GET /shirts/sizesAndPrices?sku=1001 {"1001: {"sizes": {"XS": 8.99, "S" 9.99}}}

<amp-state> 元素中的 JSON 数据类似,从这些获取操作返回的远程数据会合并到元素的 id 属性下并可供访问。例如,可以通过表达式访问从上面示例响应返回的数据

表达式 结果
shirts['1001'].sizes['XS'] 8.99

绑定数据

现在,让我们将其应用于我们的电子商务示例。首先,让我们在选择新的 SKU 时获取此衬衫数据。将 [src] 绑定添加到我们的 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">

指示不可用的尺码

接下来,让我们为给定的 SKU 清楚地标记不可用的尺码。"unavailable" CSS 类会给元素添加一条对角线 - 我们可以将其添加到 amp-selector 中与不可用尺码对应的元素中

<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>

现在,重新加载页面并尝试一下。选择新的 SKU(衬衫颜色)会导致不可用的尺码被划掉(在短暂的延迟后)。

指定初始状态

不过,有一个小问题 - 那黑色衬衫(默认选定的颜色)呢?我们需要将黑色衬衫的尺码和价格数据添加到 amp-state#shirts,因为 amp-bind 仅在响应显式用户操作时运行

<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
        }
      },
<!-- ... -->

并且,我们需要更新相关元素的默认状态

<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>

注意 – amp-bind 不会在页面加载时运行 - 仅在响应显式用户操作时运行。这确保了无论是否使用 amp-bind,初始页面加载在各个页面上始终保持快速。

可变的衬衫价格

现在我们正确显示了可用尺码,让我们确保也显示了正确的价格。

我们的 AMPPAREL 商店的特殊之处在于,衬衫价格取决于颜色和尺码。这意味着我们需要一个新的变量来跟踪用户选择的尺码。将新操作添加到我们的尺码 amp-selector 元素

<!-- 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})">

请注意,我们没有通过 amp-state#selected 元素初始化 selectedSize 的值。这是因为我们有意不提供默认选择的尺码,而是希望强制用户选择一个尺码。

提示 – 除了修改现有变量外,AMP.setState() 还可以用于定义新变量。表达式会将未定义的变量求值为 null

添加一个新的 <span> 元素,用于包装价格标签,并将默认文本更改为“---”,因为没有默认尺码选择。

<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>

我们得到了正确的价格!尝试一下。

条件启用的按钮

我们快完成了!让我们在选定的尺码不可用时禁用“添加到购物车”按钮

<!-- 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]">

尝试一下:如果你选择一个不可用的尺码,你将无法将其添加到购物车。