【问题标题】:For Loop All Products Regardless of Page Number无论页码如何,都循环所有产品
【发布时间】:2021-11-23 07:58:14
【问题描述】:

我为我们的 Shopify 商店之一编写了代码,但它没有按我想要的方式工作。我请求您对此提供支持。

这是对我们收藏页面上每件商品的检查。我得到包含产品 base_sku 名称的标签,并在所有产品中查找带有此标签的产品。 然后我从具有相同 base_sku 的产品中提取包含颜色的标签,并将它们链接到主产品下。 我在这里使用分页,我知道我最多可以拉出 1000 个项目。我需要的是能够按我想要的每个产品多次循环分页,而不管页码是多少。 因为这样一来,它只检查集合第一页的前1000个产品,而当我切换到第二页时,它会检查剩余产品的数量。

在这里我必须继续处理标签,因为虽然这里的产品似乎是变体,但我展示的所有产品都是单独的产品。 https://gyazo.com/bc139013bdb7d9ad249ca907bf4b83a1

这是我一直在处理但无法解决的问题,如果您能支持我,我将非常高兴。

最好的问候, 伯克

<div id="prod-var" class="prod-variants">
          {% for tag in product_card_product.tags %}
            {% if tag contains "BASE SKU" %}
              {% assign base_url = tag | split: "_" | last %}
            {% endif %}
            {% if tag contains "COLOUR" %}
              {% assign first_colour = tag | split: "_" | last %}
            {% endif %}
            {% if tag contains "SIZE" %}
              {% assign first_size = tag | split: "_" | last %}
            {% endif %}
          {% endfor %}
          <div class="variant-all-div">
              {% paginate collections.all.products by 1000 %}
                {% for product in collections.all.products %}
                  {% for tag in product.tags %}
                    {% if tag contains base_url %}
                        {% for tag in product.tags %}
                          {% if tag contains "COLOUR" %}
                            {% assign colour = tag | split: "_" | last %}
                          {% endif %}
                        {% endfor %}
                        {% for tag in product.tags %}
                          {% if tag contains "SIZE" %}
                            {% assign size = tag | split: "_" | last %}
                          {% endif %}
                        {% endfor %}
                        {% if first_colour == colour and first_size == size%}{% continue %}{% endif %}
                        <div class="variant-div">
                          <a class="collec-variant" href="{{product.url}}"><img style="width: 30px; height: 30px;" src="{{ product.featured_media | img_url:'30x30' }}"></a>
                          <span class="tooltiptext">{{ colour }}</span>
                        </div>
                    {% endif %}
                  {% endfor %}
                {% endfor %}
              {% endpaginate %}
          </div>
        </div>

【问题讨论】:

    标签: html shopify liquid shopify-template


    【解决方案1】:

    第 1 步:不要在 Liquid 中对大量产品进行分页

    1000 项限制是 Shopify 施加的硬限制,因为我认为这是完全合理的服务器负载原因。当为用户生成页面时,您编写的任何代码都必须在 Shopify 的服务器上运行。另请记住,Liquid 是一种模板语言,不是一种编程语言,因此针对模板功能而非复杂对象操作进行了优化!

    Shopify 编译并将页面发送到客户端浏览器所需的时间也可能会受到带有昂贵服务器操作的巨大循环的严重影响,从而显着增加用户请求您的页面与 Shopify 能够开始传输之间的延迟页面内容。我看到一些页面试图做你想做的事情的变体,并观察到 ​​TTFB(第一个字节的时间)增长到 5 秒...... 10 秒......甚至高达 20 + 极端情况下的秒数。随着加载时间的增加,您的访问者会很快决定将他们的时间花在其他地方更好!

    第 2 步:退后一步,寻找推迟获取额外内容的方法

    在这种情况下,“延迟”意味着以这样一种方式分解您的代码和逻辑,以便您可以在不中断页面的初始编译、传输和呈现的情况下开始获取信息。

    以下是我如何处理此问题的粗略概述。当然,您比互联网上的随机陌生人更了解您的具体情况,因此这是作为灵感指南而不是刻在石头上的东西。

    • Javascript 将允许我们以“异步”(非阻塞)方式从不同的 URL 获取数据并生成稍后可以插入的 HTML,所以让我们尽可能多地使用 Javascript。
    • 从 Liquid 代码中删除整个 &lt;div id="prod-var" class="prod-variants"&gt; 组件,并将其替换为占位符。我们需要能够识别占位符以及它属于哪个产品,所以让我们将其设为&lt;div class="prod-var loading" data-product-id="{{ product.id }}"&gt; (注意:如果有可能在页面我们应该使用类,而不是 ID。根据 HTML 规范,ID 应在任何给定页面上 100% 绝对唯一)
    • 可选地,在我们的 CSS 文件中,我们可以为 .prod-var.loading 制作一些样式,以便在我们获取数据时显示漂亮的加载动画或其他内容。
    • 现在让我们制作我们的 JS 文件。我们希望代码在页面初始绘制后执行,以便我们的客户可以尽快看到我们所有出色的产品,所以让我们使用 defer 属性加载它,这样它就不会运行,直到最后的 HTML 内容已加载:&lt;script src="{{ 'script-filename.js' | asset_url }}" defer&gt;&lt;/script&gt;

    在我们的 JS 文件中,我们知道我们要执行以下步骤:

    1. 获取大量产品数据
    2. 继续获取产品数据,直到我们用完为止
    3. 循环浏览页面上的所有产品
    4. 对于每个产品,为 prod-var 元素生成我们的 HTML
    5. 将 HTML 附加到适当的元素并删除 loading

    为我们的 JS 文件草拟一个粗略的想法,我们可能会有类似这样的东西:

    function populateAllProdVars(){
      // I set this up using promise-chaining notation, but you can certainly use async/await, traditional callbacks, or anything else you are comfortable with
      fetchMyProducts()
        .then(generateProdVarHTML)
        .catch(/* SOME ERROR HANDLING FUNCTION */)
    }
    
    fetchMyProducts(productListSoFar, page){
      productListSoFar = productListSoFar || []; // Setting [] as a default
      page = page || 1; // Setting page 1 as a default
    
      return fetch('/collections/all/products.json?page=' + page)
               .then(function(response){ return response.json() })
               .then(function(collectionJSON){
                 // Recursively keep going until we run out of products
                 if(collectionJSON.products.length){
                   productListSoFar = productListSoFar.concat(collectionJSON.products);
                   return fetchMyProducts(productListSoFar, page+1);
                 }
                 else {
                   // No more products, time to move on to the next step
                   return productListSoFar;
                 }
               }
    }
    
    function generateProdVarHTML(productList){
      var prodVarElements = document.querySelectorAll('.prod-var.loading');
      for(var i=0; i<prodVarElements.length; i++){
        var element = prodVarElements[e];
        var productId = element.dataset.productId;
        var relatedProducts = productList.filter(/* SOME FILTER FUNCTION */);
        var prodVarHTML = /* SOME FUNCTION TO TURN ARRAY OF RELATED PRODUCTS INTO RELEVANT HTML */
        element.innerHTML = prodVarHTML;
        element.classList.remove('loading');
      }
    }
    
    populateAllProdVars();
    

    有很多地方可以进一步改进,特别是如果您可以通过更具体的集合找到所有相关产品。您可能还需要考虑制作一个仅打印相关数据而不是获取整个 prodct.json 内容的自定义集合视图,从而为您的客户节省一些带宽并简化用户设备需要在内存中保存的对象(这可以使移动设备上的购物者受益)。我使用了默认的分页限制,但您可以通过在 collections/all/products URL 的末尾添加 &amp;limit=100(或任何您认为最合适的值)来调整它。

    希望这能让您更接近您的需求,同时也有助于提升您网站的整体性能。

    【讨论】:

      猜你喜欢
      • 2013-04-29
      • 2021-07-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多