繁体   English   中英

渲染和执行<script> on pageload after injecting it from external .js file

[英]Rendering and executing <script> on pageload after injecting it from external .js file

我仍然是 JavaScript 的初学者,正在尝试使用它来使 Etsy Mini API 响应。 我有两个<script>需要添加到<div>以便迷你商店出现:

<script type='text/javascript' src='https://www.etsy.com/assets/js/etsy_mini_shop.js'></script>
<script type='text/javascript'>new Etsy.Mini(<UNIQUE_SHOP_ID>,'thumbnail',4,3,0,'https://www.etsy.com');</script>

在第二个<script>中,我可以指定缩略图网格的大小(上例中为 4x3),但该网格没有响应性,因此如果它加载到屏幕较小的设备上,或者笔记本电脑的浏览器窗口调整大小后,4x3 网格可能太大。 我想在外部 .js 文件中使用媒体查询来更改此缩略图网格,这就是我遇到问题的地方。

以下是我当前的外部 .js 文件:

var products = document.getElementById("products-card");
var grid5x3 = "<script type='text/javascript'>new Etsy.Mini(<UNIQUE_SHOP_ID>,'thumbnail',5,3,0,'https://www.etsy.com');</script>";
var grid4x3 = "<script type='text/javascript'>new Etsy.Mini(<UNIQUE_SHOP_ID>,'thumbnail',4,3,0,'https://www.etsy.com');</script>";
var grid3x3 = "<script type='text/javascript'>new Etsy.Mini(<UNIQUE_SHOP_ID>,'thumbnail',3,3,0,'https://www.etsy.com');</script>";
var grid2x3 = "<script type='text/javascript'>new Etsy.Mini(<UNIQUE_SHOP_ID>,'thumbnail',2,3,0,'https://www.etsy.com');</script>";
var grid1x3 = "<script type='text/javascript'>new Etsy.Mini(<UNIQUE_SHOP_ID>,'thumbnail',1,3,0,'https://www.etsy.com');</script>";

(function () {
    function resize() {
        var min_2500 = window.matchMedia('only screen and (min-width: 2500px)').addListener(function () {
            products.innerText = grid5x3;
        });
        var min_1900_max_2499 = window.matchMedia('only screen and (min-width: 1900px) and ' +
        '(max-width: 2499px)').addListener(function () {
            products.innerText = grid4x3;
        });
        var min_1200_max_1899 = window.matchMedia('only screen and (min-width: 1200px) and ' +
        '(max-width: 1899px)').addListener(function () {
            products.innerText = grid3x3;
        });
        var min_900_max_1199 = window.matchMedia('only screen and (min-width: 900px) and ' +
        '(max-width: 1199px)').addListener(function () {
            products.innerText = grid2x3;
        });
        var max_899 = window.matchMedia('only screen and (max-width: 899px)').addListener(function () {
            products.innerText = grid1x3;
        });
    }

    resize();
}());

这是.html:

<head>
  ...
  <script type='text/javascript' src='https://www.etsy.com/assets/js/etsy_mini_shop.js'></script>
</head>
<body>
  ...
  <div class="products-card" id="products-card"></div>
  ...
</body>

问题 1:脚本没有被执行,而是实际的文本,包括<script>标签,出现在<div>中。 如何更改我的 Javascript 以使脚本执行并呈现迷你商店?

问题 2:页面加载时<div>为空,但在调整浏览器屏幕大小并达到媒体查询中指定的截止点之一后,文本会根据媒体查询正确显示并更改。 如何使商店在页面加载时呈现在<div>中,而不仅仅是在调整浏览器窗口大小时?

更新 1所以我发现使用 innerText/innerHTML 在注入 html 文件时不允许执行/渲染任何脚本( 基于此处的答案)。 这是我的新 .js 文件:

var products = document.getElementById("products-card");
var grid5x3 = "new Etsy.Mini(<UNIQUE_SHOP_ID>,'thumbnail',5,3,0,'https://www.etsy.com');";
var grid4x3 = "new Etsy.Mini(<UNIQUE_SHOP_ID>,'thumbnail',4,3,0,'https://www.etsy.com');";
var grid3x3 = "new Etsy.Mini(<UNIQUE_SHOP_ID>,'thumbnail',3,3,0,'https://www.etsy.com');";
var grid2x3 = "new Etsy.Mini(<UNIQUE_SHOP_ID>,'thumbnail',2,3,0,'https://www.etsy.com');";
var grid1x3 = "new Etsy.Mini(<UNIQUE_SHOP_ID>,'thumbnail',1,3,0,'https://www.etsy.com');";

(function () {
    function resize() {
        var min_2500 = window.matchMedia('only screen and (min-width: 2500px)').addListener(function () {
            var eval_grid5x3 = eval(grid5x3);
            products.innerText = eval_grid5x3;
        });
        var min_1900_max_2499 = window.matchMedia('only screen and (min-width: 1900px) and ' +
        '(max-width: 2499px)').addListener(function () {
            var eval_grid4x3 = eval(grid4x3);
            products.innerText = eval_grid4x3;
        });
        var min_1200_max_1899 = window.matchMedia('only screen and (min-width: 1200px) and ' +
        '(max-width: 1899px)').addListener(function () {
            var eval_grid3x3 = eval(grid3x3);
            products.innerText = eval_grid3x3;
        });
        var min_900_max_1199 = window.matchMedia('only screen and (min-width: 900px) and ' +
        '(max-width: 1199px)').addListener(function () {
            var eval_grid2x3 = eval(grid2x3);
            products.innerText = eval_grid2x3;
        });
        var max_899 = window.matchMedia('only screen and (max-width: 899px)').addListener(function () {
            var eval_grid1x3 = eval(grid1x3);
            products.innerText = eval_grid1x3;
        });
    }

    resize();
}());

虽然这确实渲染了 Etsy 迷你商店,但它有一些奇怪的行为:

  1. 当我期望目标<div>被脚本替换时,整个<body>被注入的脚本替换。

  2. 每次我调整屏幕大小时,它都会添加另一个 Etsy 迷你商店(它不会替换当前存在的那个),导致页面充满了许多商店。

  3. 它没有在页面加载时呈现的问题仍然存在。

抱歉,如果这是一个相当简单的问题。 我花了很多时间谷歌搜索解决方案,但我尝试过的都没有奏效。 我上面的代码是我最接近响应式 Etsy Mini 商店的代码。 感谢您的任何回答/意见/建议!

您应该始终将 JS 脚本放在 body 标记的关闭之前,这样所有内容都加载到页面上,然后执行 JS 文件,否则它会先运行文件然后加载页面,导致它不执行任何功能,因为HTML 尚未加载。 代码总是从左到右,从上到下阅读。 希望这可以帮助。

我尝试让它与“更新和刷新<script>标签”方法一起使用,但无法正确渲染。 然而,我做了一点挖掘,结果发现Etsy.Mini只是在页面中注入了一个<iframe> 如果您抓取该<iframe>并更新其中的 URL,则可以更改 Etsy Mini 的大小。

这是 Etsy Mini 加载的<iframe>示例。

<iframe frameborder="0"
    src="https://www.etsy.com/mini.php?shop_id=9999999&amp;image_type=gallery&amp;rows=5&amp;columns=5&amp;featured=0"
    width="975" height="1025">
</iframe>

关键是<iframe>src部分中的 URL。 URL 中有两个值得注意的属性rowscolumns 在呈现页面时更新这些属性将改变 Etsy Mini 的大小,从而实现类似于混蛋响应的效果。

首先,将您的 Etsy Mini 脚本标签包装在带有一些 id 的<div>中。 这使您可以轻松找到<iframe> 这将是<div>中唯一的一个,只要您除了<script>标记之外没有放置任何其他内容。

<div id="etsy-iframe-container">
    <script type='text/javascript' src='https://www.etsy.com/assets/js/etsy_mini_shop.js'></script>
    <script type='text/javascript'> new Etsy.Mini(9999999, 'gallery', 5, 5, 0, 'https://www.etsy.com');</script>
</div>

出于参考目的,由于 Etsy 已从其网站上删除了它的所有官方痕迹(但截至 2022 年它仍然有效!) Etsy.Mini的结构是。

Etsy.Mini(
    shopId (Integer), 
    type (String: 'gallery' or 'thumbnail'), 
    columns (Integer), 
    rows (Integer), 
    showUpTo4FeaturedItemsFirst (Boolean: 0 or 1), 
    etsyHomepageUrl (String: must be 'https://www.etsy.com')
)

您可以通过在此处粘贴您的商店 URL 来获取您的 Etsy 商店 ID。 将 Etsy Mini <script>标签包装在<div>中后,您可以使用下面的 JavaScript(创建自定义 JS 文件并将其加载到 HTML 文档中)通过修改其 URL 来动态调整<iframe>的大小。

这是基于对当前屏幕尺寸的了解。 单个 Etsy Mini 单元格的宽度和高度始终为184px 我通过在浏览器中检查一个发现了这一点。 有了这些知识,您就可以计算出有多少 Etsy Mini 可以水平放置在屏幕上,并相应地更新<iframe> 可以使用相同的方法来更新行数,但鉴于现在大多数浏览器都支持无限滚动,我认为这并不是真正必要的。 设置minColumnsmaxColumns允许您为 Etsy Mini 在极端情况下的外观提供一些界限。

let resizeEtsyMini = () => {
    let minColumns = 1;
    let maxColumns = 5;
    let clientWidth = document.documentElement.clientWidth;
    let etsyMiniColumns = Math.floor(clientWidth / 184);

    if (etsyMiniColumns < minColumns) {
        etsyMiniColumns = minColumns;
    }
    else if (etsyMiniColumns > maxColumns) {
        etsyMiniColumns = maxColumns
    }
    
    // Row value can be whatever, browsers have infinite scroll these days.
    setEtsyMiniSize(5, etsyMiniColumns, clientWidth);
}

let setEtsyMiniSize = (rows, columns, iframeWidth) => {
    let etsyIframe = document.getElementById("etsy-iframe-container").getElementsByTagName("iframe");
    let etsyURL = new URL(etsyIframe[0].src);
    etsyURL.searchParams.set("rows", rows);
    etsyURL.searchParams.set("columns", columns);

    etsyIframe[0].src = etsyURL.toString();
    etsyIframe[0].width = iframeWidth;
}

// On initial page load, and on every window resize, call resizeEtsyMini.
window.onload = window.onresize = resizeEtsyMini;

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM