访问购物车中产品对象中的元字段(强调自定义字段中的自定义字段)?

Liz*_*Liz 2 javascript cart shopify

我在 Shopify 项目中使用Accentuate Custom FieldsCart.js。我通过 ACF 向我的产品添加了一些自定义字段。这些字段通过 出现在产品对象上product.metafields.accentuate.[key]

我正在使用 Cart.js 自定义我的购物车体验,我希望能够访问购物车中 ACF 的一些值。

我尝试通过将以下内容添加到我的购物车布局来访问此自定义字段(每个项目都是我的 JS 循环中产品的名称):item.metafields.accentuate.product_benefits_content

但是,我收到以下错误:Uncaught TypeError: Cannot read property 'accentuate' of undefined

我也尝试过:item.product.metafields.accentuate.product_benefits_content根据我在 Stack Overflow 上找到的回复。

这给出了一个略有不同的错误:Uncaught TypeError: Cannot read property 'metafields' of undefined

我需要做什么才能访问购物车中的这些自定义字段?

这是我的控制台中产品对象的屏幕截图:

产品对象

Dav*_*e B 5

在 Shopify 上,元字段是半受保护的,不属于正常产品输出的一部分。您可以使用产品页面上的简单脚本自行测试:

<script>
  var product_info_from_liquid = {{ product | json }}
  console.log('Product info from Liquid:',product_info_from_liquid)
</script>
Run Code Online (Sandbox Code Playgroud)

注意,无论产品是否有元字段,上面都不会输出元字段。

同样,如果您从任一前端产品端点加载产品的关联 JSON 对象,则元字段将被省略。为了进行验证,我们可以通过从 Shopify 的两个前端端点获取 JSON 输出来进行测试:

<script>
  //Grabbing the data for the 'sleepy-head' product from the .js endpoint
  jQuery.ajax({
    url:'/products/sleepy-head.js',
    dataType:'json',
    success:function(product){
      console.log('The ".js" results:', product)
    }

  //Grabbing the data for the 'sleepy-head' product from the .json endpoint
  //I don't know why Shopify serves different at the .js and .json addresses, but apparently they do
  jQuery.ajax({
    url:'/products/sleepy-head.json',
    dataType:'json',
    success:function(product){
      console.log('The ".json" results:', product)
    }

  })

</script>
Run Code Online (Sandbox Code Playgroud)

我们再次注意到,无论我们尝试以哪种方式获取信息,我们的请求都不会提供元字段数据。

这给我们带来了一个最初令人沮丧的认识:元字段只能通过Liquid 访问

所以,我们能做些什么?

元字段是半受保护的:您必须知道命名空间存在并在 Liquid 中访问它。我认为,这在一定程度上是为了为依赖元字段来做任何事情的应用程序提供一层保护。(例如,如果了解 Shopify 如何工作的潜在客户可以打开一个窗口,显示某些应用程序的有关获得更优惠价格资格的元数据)

不管怎样,我们需要创建新变量来存储我们需要的元数据,然后在 JS 循环中使用该变量。

我们有多种选择可供选择,选择哪一种完全取决于您。这里有两个想法:

思路一:在页面上创建全局变量

这通常是最简单的,但创建大量全局变量可能会被认为是草率的。此外,Liquid 仅在页面加载时呈现,因此如果您的网站非常动态,您可能会发现客户操作可能导致您未加载所有元数据的情况。

为此,我们将在 Javascript 中创建一个对象,该对象对页面上我们可能关心的每个产品使用唯一标识符 - 最明显的选择是产品的 ID 或产品的句柄,因为这两者都保证是独一无二的。

由于我们只保存相关应用程序/功能的元数据,而不保存产品上可能存在的每个元字段,因此让我们创建一个名为的代码片段save-accentuate-metadata.liquid来保存逻辑:

<script>
  // Initialize our global object only if it doesn't exist yet
  window.AccentuateLookup = window.AccentuateLookup || {}
  AccentuateLookup[{{ product.handle | json }}] = {{ product.metafields.accentuate | json }} 
</script>
Run Code Online (Sandbox Code Playgroud)

现在我们只需要在有产品对象的地方包含它 - 产品页面、集合产品循环等。我们期望product在代码片段中命名一个变量,所以让我们在代码片段调用中明确这一点:

 {% include 'save-accentuate-metadata', product: product %}
Run Code Online (Sandbox Code Playgroud)

如果我们的代码有可能需要能够在搜索页面上运行,那么包含将需要引用搜索页面上调用的任何变量(通常result):

 {% if result.object_type == 'product' %}
   {% include 'save-accentuate-metadata', product: result %}
 {% endif %}
Run Code Online (Sandbox Code Playgroud)

最后,我们要确保保存购物车中当前商品的所有元字段数据。我们会将此调用放在全局某个地方,例如在layout/theme.liquid中(或者我们在theme.liquid中包含的片段)

{% for item in cart.items %}
  {% include 'save-accentuate-metadata', product: item.product %}
{% endfor %}
Run Code Online (Sandbox Code Playgroud)

现在我们已经保存了所有这些信息,只要我们有产品句柄,我们就可以在我们需要的任何脚本中访问它。

// Meanwhile, in some other script on the page:
if(typeof AccentuateLookup === 'undefined'){
  console.error('No data initialized!')
}
var accentuate_data = AccentuateLookup[item.handle]
console.log('Our records show the following for' + item.title, accentuate_data)
Run Code Online (Sandbox Code Playgroud)

想法 2:创建我们自己的自定义端点

这需要更多的工作,但它为您提供了自己的端点,您可以在需要时随时访问该端点来获取所需的数据。这可以让您对网站上运行的奇特功能或应用程序更加敏感,这些功能或应用程序可以操纵购物车或加载最初不在页面上的产品(例如追加销售式应用程序)。请注意,采用此方法意味着您需要进行异步 AJAX 调用来获取数据,这可能会在数据加载时产生延迟。

要创建自定义端点,我们首先为要从中获取数据的对象类型创建一个新模板。让我们创建两个:一个用于购物车,它将提供购物车商品的所有数据,另一个用于单个产品。

让我们首先创建一个名为cart.accentuate.json.liquid以下内​​容的模板:

{% layout none %} {% comment %} That tells Shopify to ignore all the layout code/HTML, freeing us to create a simple JSON object {% endcomment %}
{
  {% for item in cart.items %}
    {% comment %}Output the JSON data, and append a comma unless we're on the last one{% endcomment %}
    {{ item.handle | json }}: {{ item.product.metafields.accentuate | json }}{% unless forloop.last %},{% endunless %}
  {% endfor %}
}
Run Code Online (Sandbox Code Playgroud)

以防万一我们只想获取一种产品,让我们为product.accentuate.json.liquid. 由于我们要获取特定产品,因此除了元数据之外我们可能不需要任何其他内容:

{% layout none %}
{{ product.metafields.accentuate | json }}
Run Code Online (Sandbox Code Playgroud)

view现在,我们可以通过在查询字符串中指定与模板后缀匹配的a,使用 AJAX 调用从任意代码段访问其中任何一个。例如:

jQuery.ajax({
  url:'/cart?view=accentuate.json',
  success:function(unparsed_json){
    var cart_data = JSON.parse(unparsed_json)
    console.log('This just in from cart.accentuate.json:', cart_data)
  }
})

var handle = 'sleepy-head'
jQuery.ajax({
  url:'/products/' + handle + '?view=accentuate.json',
  success:function(unparsed_json){
    var cart_data = JSON.parse(unparsed_json)
    console.log('This just in from product.accentuate.json:', cart_data)
  }
})
Run Code Online (Sandbox Code Playgroud)

请注意,当我们以这种方式创建自定义端点时,Shopify 将像常规 HTML 页面一样提供其响应。如果我们尝试指定我们期待 JSON 响应,这可能会导致 jQuery 的 AJAX 函数表现得很奇怪。发现所有意外行为留给读者作为练习,但要点是您希望像常规 HTML 页面一样获取页面,然后用于将JSON.parse检索到的文本转换为正确的 JSON 对象。

我希望这可以帮助您完成您正在开发的功能!


免责声明:以上所有代码都是自由编写的,并且没有经过拼写错误测试。如果有任何东西不能立即工作,请评论、编辑和/或检查任何明显的错误代码语法