AMP
  • 网站

产品页面

简介

此示例展示了如何在 AMP HTML 中构建产品页面。

元数据

页面索引需要以下类型之一的 schema.org 标记:Type、AggregateRating、Offers。 了解更多

<script type="application/ld+json">
{
    "@context": "http://schema.org/",
    "@type": "Product",
    "name": "Apple",
    "image": "https://amp.js.cn/static/samples/img/golden_apple1_1024x682.jpg",
    "description": "Lorem ipsum",
    "mpn": "925872",
    "brand": {
        "@type": "Fruit",
        "name": "Apple"
    },
    "aggregateRating": {
        "@type": "AggregateRating",
        "ratingValue": "4.4",
        "reviewCount": "88"
    },
    "offers": {
        "@type": "Offer",
        "priceCurrency": "USD",
        "price": "1.99",
        "priceValidUntil": "2020-11-05",
        "itemCondition": "http://schema.org/UsedCondition",
        "availability": "http://schema.org/InStock",
        "seller": {
            "@type": "Retail",
            "name": "AMP by Example"
        }
    }
}
</script>

使用 amp-sidebar 组件,让客户有机会快速跳转到您的任何产品类别。

<amp-sidebar id="drawermenu" layout="nodisplay">
  <a href="/" class="caps text-decoration-none block p1">Products</a>
  <hr/>
  <a class="caps text-decoration-none block p1" href="/samples_templates/product_browse_page/preview/">Fruit</a>
  <a class="caps text-decoration-none block p1" href="/samples_templates/product_browse_page/preview/">Vegetable</a>
  <a class="caps text-decoration-none block p1" href="/samples_templates/product_browse_page/preview/">More</a>
</amp-sidebar>

AMP 支持表单,这意味着您可以将产品搜索直接集成到您的 AMP 中。尝试搜索“Apple”。

您可以使用 CSS3 动画来丰富您的页面。当搜索框获得焦点时,扩展文本字段仅使用 CSS 实现。

<div class="header">
  <a id="sample-menu" on="tap:drawermenu.toggle">
    <amp-img srcset="/static/samples/img/ic_menu_white_1x_web_24dp.png 1x, /static/samples/img/ic_menu_white_2x_web_24dp.png 2x"
            width="24" height="24"
            alt="navigation"></amp-img>
  </a>
  <form method="GET" action="/documentation/examples/api/search" target="_top">
    <input name="search" type="search" placeholder="Search">
    <a id="sample-logo" href="/">Product</a>
    <input type="submit" value="">
  </form>
</div>

社交分享

社交分享扩展为共享按钮提供了一个通用接口。在此处了解有关 amp-social-share 的更多信息 here

<div class="m1">
  <amp-social-share type="twitter"
                    width="30"
                    height="22"></amp-social-share>
  <amp-social-share type="facebook"
                    width="30"
                    height="22"
                    data-attribution="254325784911610"></amp-social-share>
  <amp-social-share type="email"
                    width="30"
                    height="22"></amp-social-share>
  <amp-social-share type="pinterest"
                    width="33"
                    height="22"></amp-social-share>
</div>

视频

AMP 支持各种视频平台。这里我们使用 amp-youtube 来显示产品视频。您可以在 此处找到所有受支持的视频平台的概述。

在此示例中,我们不将视频直接嵌入到页面中,而是使用 amp-lightbox 组件将其显示在灯箱中。在此处了解有关 amp-lightbox 的更多信息 here

<button class="ampstart-btn caps m1 mb3" on="tap:watch-video-lightbox" >
  Show Video
</button>

在桌面上,我们添加了一个类似胶片的幻灯片预览。每种产品颜色都有自己的图像库和幻灯片预览。我们使用 amp-bind 来更新页面,选择与所选颜色对应的图库和图像预览。我们通过使用 amp-selector 实现了颜色选择。在下面的产品页面部分中查找更多文档和信息。

绿色是页面加载时图库的默认颜色。单击预览图像将通过点击操作 on="tap:AMP.setState({product: {selectedSlideForGreen: 0}})" 在图库中显示图像。

请参阅下文,了解有关我们如何使用 amp-bind 的更多信息。

<div class="product-gallery">
  <ul [hidden]="product.selectedColor != 'green'">
    <li>
      <amp-img on="tap:AMP.setState({product: {selectedSlideForGreen: 0}})"
                src="/static/samples/img/green_apple_1_60x40.jpg"
                width="60" height="40"
                class="selected"
                [class]="product.selectedSlideForGreen == 0 ? 'selected' : '' "
                tabindex="0" role="button">
      </amp-img>
    </li>
    <li>
      <amp-img on="tap:AMP.setState({product: {selectedSlideForGreen: 1}})"
                src="/static/samples/img/green_apple_2_60x40.jpg"
                width="60" height="40"
                [class]="product.selectedSlideForGreen == 1 ? 'selected' : '' "
                tabindex="1" role="button">
      </amp-img>
    </li>
  </ul>

  <ul hidden [hidden]="product.selectedColor != 'golden'">
    <li>
      <amp-img on="tap:AMP.setState({product: {selectedSlideForGolden: 0}})"
              src="/static/samples/img/product1_alt1_60x40.jpg"
               width="60" height="40"
               class="selected fadeIn"
               [class]="product.selectedSlideForGolden == 0 ? 'selected fadeIn' : '' "
               tabindex="0" role="button">
      </amp-img>
    </li>
  </ul>

  <ul hidden [hidden]="product.selectedColor != 'red'">
    <li>
      <amp-img on="tap:AMP.setState({ product: {selectedSlideForRed : 0}})"
               src="/static/samples/static/samples/img/red_apple_1_60x40.jpg"
               width="60" height="40"
               class="selected fadeIn"
               [class]="product.selectedSlideForRed == 0 ? 'selected fadeIn' : '' "
               tabindex="0" role="button">
      </amp-img>
    </li>
    <li>
      <amp-img on="tap:AMP.setState({ product: {selectedSlideForRed : 1}})"
               src="/static/samples/static/samples/img/red_apple_2_60x46.jpg"
               width="60" height="40"
               [class]="product.selectedSlideForRed == 1 ? 'selected' : '' "
               tabindex="1" role="button">
      </amp-img>
    </li>
  </ul>
</div>

amp-carousel 组件非常适合产品图片库。了解 amp-carousel 组件的工作原理 here

请注意,我们如何使用变量 selectedSlideForGreenselectedColor 的值绑定到 slideclass

<div class="product-gallery">

  <amp-carousel id="green-apple-carousel"
          width="1024" height="682"
          layout="responsive"
          type="slides"
          [slide]="product.selectedSlideForGreen"
          on="slideChange: AMP.setState({product: {selectedSlideForGreen: event.index}})"
          class="fadeIn"
          [hidden]="product.selectedColor != 'green'">
    <amp-img src="/static/samples/img/green_apple_1_1024x682.jpg"
              width="1024" height="682"
              layout="responsive" on="tap:gallery-lightbox"
              role="button" tabindex="0">
    </amp-img>
    <amp-img src="/static/samples/img/green_apple_2_1024x685.jpg"
              width="1024" height="682"
              layout="responsive" on="tap:gallery-lightbox"
              role="button" tabindex="0">
    </amp-img>
  </amp-carousel>

  <amp-carousel id="golden-apple-carousel"
          width="1024" height="682"
          layout="responsive"
          type="slides"
          [slide]="product.selectedSlideForGolden"
          on="slideChange: AMP.setState({product: {selectedSlideForGolden: event.index}})"
          hidden
          class="fadeIn"
          [hidden]="product.selectedColor != 'golden'">
      <amp-img src="/static/samples/img/golden_apple1_1024x682.jpg"
              width="1024" height="682"
              layout="responsive" on="tap:gallery-lightbox"
              role="button" tabindex="0">
      </amp-img>
  </amp-carousel>

  <amp-carousel id="red-apple-carousel"
          width="1024" height="682"
          layout="responsive"
          type="slides"
          [slide]="product.selectedSlideForRed"
          on="slideChange: AMP.setState({product: {selectedSlideForRed: event.index}})"
          hidden
          class="fadeIn"
          [hidden]="product.selectedColor != 'red'">
      <amp-img src="/static/samples/img/red_apple_1_1024x682.jpg"
              width="1024" height="682"
              layout="responsive" on="tap:gallery-lightbox"
              role="button" tabindex="0">
      </amp-img>
      <amp-img src="/static/samples/img/red_apple_2_1024x793.jpg"
              width="1024" height="682"
              layout="responsive" on="tap:gallery-lightbox"
              role="button" tabindex="0">
      </amp-img>
  </amp-carousel>
</div>

全屏图片

amp-image-lightbox 组件允许用户展开图像以填充视口。通过单击产品图库中的每个图像,用户可以使用全屏查看产品图像。在此处了解更多信息 here

<amp-image-lightbox id="gallery-lightbox" layout="nodisplay">
  <div on="tap:gallery-lightbox.close" role="button"
      tabindex="0">
      <button class="ampstart-btn caps m2 close-gallery-button" on="tap:gallery-lightbox.close"
        role="button" tabindex="0">
        Close
      </button>
  </div>
</amp-image-lightbox>

产品配置

我们使用 amp-state 组件(amp-bind 的一部分)

根据颜色和尺寸配置产品价格。我们还配置 defaultSize

当您在颜色之间切换时,对于每种产品,以及您先前选择的尺寸对于新颜色不可用时

<amp-state id="product">
  <script type="application/json">
  {
    "selectedColor": "green",
    "selectedSize": "S",
    "selectedSlideForRed": 0,
    "selectedSlideForGolden": 0,
    "selectedSlideForGreen": 0,
    "moreItemsPageIndex": 0,
    "hasMorePages": true,
    "green": {
      "id": "1",
      "sizes": {
        "S": "$5.99",
        "M": "$5.99",
        "L": "unavailable"
      },
      "defaultSize": "S"
    },
    "golden": {
      "id": "2",
      "sizes": {
        "S": "$9.99",
        "M": "unavailable",
        "L": "$9.99"
      },
      "defaultSize": "L"
    },
    "red": {
      "id": "3",
      "sizes": {
        "S": "$7.99",
        "M": "$7.99",
        "L": "$7.99"
      },
      "defaultSize": "M"
    }
  }
  </script>
</amp-state>

产品价格

我们使用 amp-bind 更新产品价格

取决于所选颜色。

我们将 text 属性绑定到表达式 product[product.selectedColor].sizes[product.selectedSize] 的值。 product 是产品配置部分中描述的 amp-state json 的 id。

请注意,我们将 1.99 美元的值设置为价格的默认值:表达式不会在页面加载时进行评估。

我们使用 amp-selector 以及 amp-bind 来更新页面,以显示价格、尺寸可用性、图库和图像预览。每次您选择一种颜色时,我们都会使用 {selectedColor: event.targetOption} 调用 AMP.setState。这将触发所有绑定到 selectedColor 的属性和元素进行更新:价格(与属性 [text] 绑定)、图库、图像预览和尺寸选择器(所有都与 [class] 绑定)。

价格:$5.99

<p class="price-description">Price:
  <span [text]="product[product.selectedColor].sizes[product.selectedSize]">$5.99</span>
</p>

产品页面

添加到购物车操作是使用 amp-form 实现的。在我们的示例中,我们使用 amp-selector 来选择不同的产品属性。按下 添加到购物车 按钮会将产品添加到购物车页面,并使用您选择的属性。请注意,按钮 URL 包含查询 clientId={{ClientId}}。如果商品成功添加到购物车,我们会将用户重定向到购物车页面。重定向目标是通过服务器表单响应中的标头配置的(提交后重定向

access-control-expose-headers:AMP-Access-Control-Allow-Source-Origin,AMP-Redirect-To amp-redirect-to:http://ampbyexample.com/shopping_cart/?clientid=amp-123456789

我们使用 CLIENT_ID 变量来识别用户,这使得可以在 AMP 页面的重复访问之间(通过 AMP 缓存或原始主机)存储购物车。可以通过声明一个带有 default-value="CLIENT_ID(cart) 的隐藏输入值来在 amp-form 中使用此变量。在此处阅读有关变量替换的更多信息 here

  • 1
  • 2
  • 3
  • S
  • M
  • L
<form id="order" method="POST"
      action-xhr="/documentation/examples/e-commerce/shopping_cart/add-to-cart"
      target="_top" class="flex flex-wrap m1">
  <div class="items-center flex">
    <label for="color">Color:</label>
    <amp-selector name="color"
            layout="container"
            [selected]="product.selectedColor"
            on="select:AMP.setState({
              product: {
                selectedColor: event.targetOption,
                selectedSlideForRed: 0,
                selectedSlideForGreen: 0,
                selectedSlideForYellow: 0,
                selectedSize: product[event.targetOption].sizes[product.selectedSize] != 'unavailable' ? product.selectedSize : product[event.targetOption].defaultSize
              }
            })">
      <ul class="p0 m1">
        <li>
          <div option="green" selected class="square green"></div>
        </li>
        <li>
          <div option="golden" class="square golden"></div>
        </li>
        <li>
          <div option="red" class="square red"></div>
        </li>
      </ul>
    </amp-selector>
  </div>
  <div class="items-center flex">
    <label for="quantity">Quantity:</label>
    <amp-selector name="quantity" layout="container">
      <ul class="p0 m1">
        <li option="1" selected>1</li>
        <li option="2">2</li>
        <li option="3">3</li>
      </ul>
    </amp-selector>
  </div>
  <div class="items-center flex">
    <label for="size">Size:</label>
    <amp-selector name="size" layout="container"
            on="select:AMP.setState({ product: {selectedSize: event.targetOption}})"
            [selected]="(product[product.selectedColor].sizes[product.selectedSize] != 'unavailable')
                ? product.selectedSize
                : product[product.selectedColor].defaultSize">
      <ul class="p0 m1">
        <li option="S" class=""
            [class]="(product[product.selectedColor].sizes['S'] != 'unavailable')
                ? ''
                : 'unavailable'">S</li>
        <li option="M" class="" selected
            [class]="(product[product.selectedColor].sizes['M'] != 'unavailable')
                ? ''
                : 'unavailable'">M</li>
        <li option="L" class="unavailable"
            [class]="(product[product.selectedColor].sizes['L'] != 'unavailable')
                ? ''
                : 'unavailable'">L</li>
      </ul>
    </amp-selector>
  </div>
  <div class="items-center flex my1">
    <input type="submit" class="ampstart-btn caps" name="add-to-cart" value="add to cart">
  </div>
  <input type="hidden" name="name" value="Apple">
  <input type="hidden" name="price" value="$1.99" [value]="product[product.selectedColor].sizes[product.selectedSize]">
  <input type="hidden" name="id" value="1" [value]="product[product.selectedColor].id">
  <input name="clientId" type="hidden" value="CLIENT_ID(cart)" data-amp-replace="CLIENT_ID">
  <div submit-error>
    <template type="amp-mustache">
      Error! Looks like something went wrong with your shopping cart, please try to add an item again. {{error}}
    </template>
  </div>
</form>

选项卡面板

使用样式设置为选项卡面板的 amp-selector 来添加有关您的产品的其他数据。了解如何在 AMP 中实现选项卡 here

水果富含维生素和矿物质。 Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat。
食用前务必清洗水果。Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum。
尺寸可能有所不同。Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua。
<amp-selector role="tablist"
layout="container"
class="ampTabContainer ampstart-headerbar-nav" keyboard-select-mode="select">
<div role="tab"
  class="tabButton h4 ampstart-nav-item"
  selected
  option="a">ABOUT</div>
<div role="tabpanel"
    class="tabContent p1 p">Fruit is rich in vitamins and minerals. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</div>
<div role="tab"
  class="tabButton h4 ampstart-nav-item"
  option="b">SPECS</div>
<div role="tabpanel"
  class="tabContent p1 p">Always wash fruit before eating. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</div>
<div role="tab"
    class="tabButton h4 ampstart-nav-item"
    option="c">SIZE</div>
<div role="tabpanel"
    class="tabContent p1 p">Size may vary. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</div>
</amp-selector>

使用 AMP,您可以轻松地引入不同的最新优惠或亮点,而无需更改页面。为此,只需使用 amp-list 向 JSON 端点触发 CORS 请求,该端点提供相关产品列表。这些产品在客户端上填充到 amp-mustache 模板中。了解有关 amp-list 的更多信息 here

<amp-list class="items m1"
          width="auto"
          height="145"
          layout="fixed-height"
          src="/static/samples/json/related_products.json"
          [src]="myState.items"
          binding="no"
          id="show-more-list">
  <template type="amp-mustache">
    <a class="text-decoration-none p1"
      href="/documentation/examples/e-commerce/product_page/preview/">
      <amp-img width="70.31"
               height="46.8"
               layout="fixed"
               alt="{{name}}"
               src="{{img}}"></amp-img>
             <p class="name">{{name}}</p>
             <p class="star">{{{stars}}}</p>
             <p class="price">${{price}}</p>
     </a>
  </template>
</amp-list>

虽然目前 AMP 中无法实现无限滚动,但您可以使用 amp-bind 动态更改 amp-list 的 src,并在页面上添加更多项目。我们将 src 属性绑定到 amp-state 组件的 id,以便 amp-list 将使用该组件中的项目作为 srcamp-state 的初始值通过将 src 值设置为与 amp-list 使用的同一端点来设置。每当用户点击“显示更多”按钮时,我们都会将项目追加到 amp-state,请参阅下文了解更多信息。

<amp-state id="myState" src="/static/samples/json/related_products.json">
</amp-state>

您可以使用 amp-formsubmit-success 事件来显示或隐藏“显示更多”按钮:请注意我们如何根据服务器响应将 hasMorePages 变量设置为 false。

<form method="GET"
    action="/documentation/examples/api/json/more_related_products_page"
    action-xhr="/documentation/examples/api/json/more_related_products_page"
    target="_top"
    on="submit-success: AMP.setState({
      myState: { items: myState.items.concat(event.response.items)},
      product: {moreItemsPageIndex: product.moreItemsPageIndex + 1,
                hasMorePages: event.response.hasMorePages}
    });">
  <input type="hidden" name="moreItemsPageIndex" value="0" [value]="product.moreItemsPageIndex">
  <input type="submit" value="Show more"
    class="ampstart-btn caps m1 mb3"
    [hidden] = "!product.hasMorePages">
</form>

用户分析

必须在 body 中配置分析。这里我们使用 Google Analytics 来跟踪页面浏览量。

<amp-analytics type="googleanalytics">
  <script type="application/json">
      {
        "vars": {
            "account": "UA-73836974-1"
        },
        "triggers": {
            "default pageview": {
                "on": "visible",
                "request": "pageview",
                "vars": {
                    "title": "Product"
                }
            }
        }
    }
  </script>
</amp-analytics>
需要进一步解释吗?

如果本页的解释没有涵盖您的所有问题,请随时与其他 AMP 用户联系,讨论您的具体用例。

前往 Stack Overflow
未解释的功能?

AMP 项目强烈鼓励您的参与和贡献!我们希望您能成为我们开源社区的持续参与者,但我们也欢迎您为自己特别感兴趣的问题做出一次性贡献。

在 GitHub 上编辑示例