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 的更多信息,请点击此处

<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 的更多信息,请点击此处

<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 组件的工作原理,请点击此处

请注意,我们如何使用变量 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 组件,用户可以将图像展开以填充视口。通过点击产品图库中的每张图像,用户可以使用全屏查看产品图像。了解更多信息,请点击此处

<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-selectoramp-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 内使用此变量。阅读有关变量替换的更多信息,请点击此处

  • 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 中实现选项卡,请点击此处

水果富含维生素和矿物质。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 的更多信息,请点击此处

<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 上编辑示例