【问题标题】:Use Javascript to write src attribute as data-src, as page is loading使用 Javascript 将 src 属性写入 data-src,因为页面正在加载
【发布时间】:2015-04-11 13:04:32
【问题描述】:

背景:早在 12 月,我想要我的(自定义)PHP 页面构建 如果用户代理 (UA) 可以处理,引擎将单向构建页面 如果 UA 不能,Javascript 和另一种方式。为了实现这一点,我 需要学习:

在 PHP 即时构建页面之前,如何通过 PHP 检测 UA Javascript 功能: Detecting javascript in PHP, before PHP builds page

感谢@skobaljic、@Abhi Beckert 提供的一些非常有用的指导 和@GolezTrol,我了解到我们可以使用 Javascript 来放置 PHP 将能够在所有后续页面上查询的会话 cookie 负载。因此,对于第一页之后的每一页,PHP 都会 知道 UA 是否支持 Javascript

到目前为止,一切都很好。现在我已经到了我不再是的阶段 使用 PHP 即时构建页面,但预先生成它们并上传 它们作为静态 HTML 文档发送到服务器。

如果你还在我身边,你会猜对了,这意味着我在 当前需要为每个页面预先生成 两个 静态文档 - one 用于不支持 JS 的 UA,one 用于支持 JS 的 UA。 这不是很理想,因此我的问题如下。

从表面上看,这应该是一个简单的问题。

对于不支持 Javascript 的 UA,我想构建一个包含以下行的文档:

<img src="/myfolder/myimage.png" alt="My Image" />

对于支持 Javascript 的 UA,我想构建包含如下行的相同文档:

<img data-src="/myfolder/myimage.png" alt="My Image" />

(对于那些好奇的人,onload 之后的 javascript 将所有 data-src 属性转换为 src 属性,随后会发生数十次服务器往返,但 - 至关重要 - 仅在 页面已经大量加载)。

我已经通过 PHP 和会话 cookie 实现了这一点(参见上面的背景),但现在,如果可能的话,我想在前端执行整个操作。

如何将属性写入 DOM 中的 &lt;img /&gt; 元素,默认为 src,但另外(如果 javascript 可用)为该属性添加前缀 data-,使其读取为 data-src。 ..

...这样...

[重要信息]

如果 UA 支持 javascript,它会在页面被UA,以便在onload 之后,javascript 可以将所有data-src 的实例重新编写为src

【问题讨论】:

    标签: javascript html user-agent


    【解决方案1】:

    像这样 - 未经测试但应该可以工作:

    var imgs = document.getElementsByTagName('img');
    
    for(var i = 0; i < imgs.length; i++) {
      var currentSrc = imgs[i].getAttribute('src');
      imgs[i].setAttribute('src',''); // remove old src data 
      imgs[i].setAttribute('data-src','currentSrc');
    }
    

    这只是添加一个新的data-src 属性,并清除当前的src(如果需要)

    &lt;/body&gt;标签之前添加

    【讨论】:

    • 谢谢@Darren,这几乎正是我所得到的(目前)相反的东西。我编写了一个脚本,它获取初始 DOM 中的所有 data-src 属性,并在 onload 之后将它们重写为 src 属性。 (提示所有服务器往返行程......)。但是......我不能默认情况下假设 JS 功能,所以我真正需要的是支持 Javascript 的 UA 首先将这些属性写为 data-src 因为页面正在被 UA 访问 i> - 所以脚本可能需要在我想的&lt;head&gt; 中。
    • 总之,一个不支持 JS 的 UA,只是将属性读取为 src,而支持 JS 的 UA,在页面加载期间将属性重写为 data-src,然后, onload,将所有data-src 属性(第二次)重写为src(提示所有服务器往返...)
    • 如果启用了 JS,我想您使用的是 data-src 的内容?只需添加两者。如果没有 JS,data-src 将被忽略,如果有 JS,无论您使用 data-src 做什么都会找到它。
    • 你说得对@Darren,如果没有JS,data-src 将被忽略。但是...src不会被忽略如果有 JS。这就是我试图利用的行为:如果有 JS,现在不要尝试加载图像,我们会在之后这样做;如果没有 JS,好吧,您可以在遇到每个图像时开始加载它(尽管所有预加载服务器往返,页面会花费更长的时间才能出现)。
    • 非常令人沮丧。我所需要的(从一个角度来看)是一个 .js 语句(每个不支持 JS 的 UA 都会忽略该语句),它将在每个 @ 实例之前立即注入 5 个字符串变量 data- 987654341@ 页面正在下载...但我不清楚如何在 HTML 元素中包含 .js 变量。所以在文档&lt;head&gt; 中,我可以有:&lt;script&gt;var asyncImg = 'data-';&lt;/script&gt;... 但是我不确定如何从那里开始。
    【解决方案2】:

    这是一种 hacky 方式,但所有浏览器 (ie6+) 都支持它:

    <body>
    
        <noscript>
             <style>.img-hide { display: none; }</style>
        </noscript>
    
        <noscript><img src="/path/to/image1.jpg"></noscript>
        <img class="img-hide" data-src="/path/to/image1.jpg">
    
        <noscript><img src="/path/to/image2.jpg"></noscript>
        <img class="img-hide" data-src="/path/to/image2.jpg">
    
        <!-- etc etc etc -->
    
    </body>
    

    【讨论】:

    • 哈哈。我喜欢它。谢谢你,@Darren。这可能不会是我最终实施的解决方案,但提醒您&lt;noscript&gt; 总是作为最后的手段总是存在的。
    • 对。我要出去跑步。它有时会带来灵感。感谢您今天下午在此花费的所有时间@Darren - 非常感谢。
    【解决方案3】:

    经过近 3 天的挠头,我终于破解了这个。

    头部

    <head>
    
    <script>
    function initialiseImages() {
            var scripts = document.getElementsByTagName('script');
            var section = scripts[scripts.length-1].parentNode;
            var images = section.getElementsByTagName('img');
            for (var i = 0; i < images.length; i++) {
                            var src = images[i].getAttribute('src');
                            var datasrc = document.createAttribute('data-src');
                            datasrc.value = src;
                            images[i].setAttributeNode(datasrc);
                            images[i].removeAttribute('src');}}
    </script>
    
    </head>
    

    身体

    <body>
    
    <section>
    <h2><img src="/myfolder/myimage.png" alt="My Image" />Second Level Heading</h2>
    <ul><li><img src="/myfolder/myimage.png" alt="My Image" /></li></ul>
    <script>initialiseImages();</script>
    </section>
    
    <section>
    <h3>Third Level Heading</h3>
    <ul>
    <li><img src="/myfolder/myimage.png" alt="My Image" /></li>
    <li><img src="/myfolder/myimage.png" alt="My Image" /></li>
    <li><img src="/myfolder/myimage.png" alt="My Image" /></li>
    </ul>
    <script>initialiseImages();</script>
    </section>
    
    </body>
    

    更新 1

    感谢 Dave Walsh 的文章Referencing a Script's own Tag (http://davidwalsh.name/script-tag),我重写了function initialiseImages()的前3行:

        var scripts = document.getElementsByTagName('script');
        var section = scripts[scripts.length-1].parentNode;
        var images = section.getElementsByTagName('img');
    

    单行:

    var images = document.currentScript.parentNode.getElementsByTagName('img');
    

    据我所知,这定义了 var images 的速度稍快一些,因此在 UA 向服务器发送文件请求之前捕获了更多 &lt;img src= 的实例。


    开发者注释如下...

    尝试 #1:尝试让 Javascript 表现得像 PHP

    比起部署 Javascript,我更熟悉用 PHP 动态编写页面,所以我的初衷是想找到一种方法,以准服务器端的方式使用 Javascript 来重写 DOM在它到达的那一刻瞬间:

    对于不支持 Javascript 的 UA,我想构建一个文档 包含这样的行:

    <img src="/myfolder/myimage.png" alt="My Image" />
    

    对于支持 Javascript 的 UA,我想构建相同的文档 包含这样的行:

    <img data-src="/myfolder/myimage.png" alt="My Image" />
    

    如果这样的方法可行,我也找不到办法——而且,公平地说,Javascript 肯定不是为在元素属性到达时立即重写元素而设计的。

    尝试 #2:通过添加 Javascript 的 CSS 阻止图片下载

    我的第二种方法是看看我是否可以通过一行 CSS 阻止图片下载。

    如果我用 Javascript 添加该行,则只有支持 Javascript 的 UA 才能读取图像阻止样式规则。

    这也不起作用。事实证明,您可以直接阻止 CSS background-images 下载,方法是将display:none; 应用于具有background-image 的元素的父容器。但是我想要阻止的图像(直到 onload 之后)具体是&lt;img&gt;s,而不是background-images - 结果表明,一旦 UA 命中&lt;img src,它就会运行到服务器下载图像。

    尝试 #3:在每个 &lt;img&gt; 中嵌入 Javascript

    内联 Javascript 相当老派,但@Darren Sweeney 已经提出了一个富有想象力的&lt;noscript&gt; 解决方案,所以我不想自动放弃老派。我想过这样解决这个问题:

    <img src="/myfolder/myimage.png" alt="My Image" onEvent="initialiseImage();" />
    

    我在这里遇到的主要问题是我找不到任何合适的onEvent。我将initialiseImage() 函数放在&lt;head&gt; 中,然后我希望每次UA 达到&lt;img&gt; 时自动触发该函数 - 但经过大量阅读,我不确定是否可以内联自动执行。 (也许有人可以在下面的 cmets 中告诉我,如果是...)

    当然,我找不到onParse

    唯一有意义的特定于元素的onEventonLoad,在&lt;img&gt; 的情况下(如果我理解正确的话)会在&lt;img&gt; 触发之前下载它。所以这根本不好。

    尝试 #4:终于成功了!

    到目前为止:

    1) 从一开始,问题就在于等到window.onload 再使用Javascript 重写每个&lt;img src= 属性为时已晚;

    2) 我看不到使用 Javascript 在下载时立即重写每个 &lt;img src= 的方法;

    3) 在 UA 解析 &lt;img&gt; 时,我看不到使用 Javascript 重写每个 &lt;img src= 属性的方法;

    我推断,在 UA 完成对包含每组 &lt;img&gt;s 的每个 &lt;section&gt; 的解析时,也许我仍然可以使用 Javascript 重写每个 &lt;img src= 属性。

    我很高兴地说,我已经相当彻底地测试了上面的代码,并且它(到目前为止)似乎可以完美运行 - 早在 UA 开始从服务器请求 &lt;img&gt; 文件之前,&lt;img src= 属性已经替换为 &lt;img data-src= 属性,并且不再执行该请求。

    【讨论】:

      猜你喜欢
      • 2019-11-14
      • 1970-01-01
      • 1970-01-01
      • 2017-12-13
      • 1970-01-01
      • 2013-04-25
      • 1970-01-01
      • 2014-09-09
      • 2017-05-22
      相关资源
      最近更新 更多