通过 PHP 循环动态添加 <img> 标记,通过在每个循环上调用 JavaScript 函数

Posted

技术标签:

【中文标题】通过 PHP 循环动态添加 <img> 标记,通过在每个循环上调用 JavaScript 函数【英文标题】:Dynamically add <img> tags with via PHP loop, via calling a JavaScript function on each loop 【发布时间】:2019-06-05 13:45:51 【问题描述】:

我有一个 php 函数,它遍历数据库中的图像结果,用 html 格式化它们,然后将包含 HTML 布局的变量返回到我的 page.php。这一切正常,但在循环中,我有一些脚本标签调用我的 script.js 文件中的函数。它需要两个参数(url 和 count)。我正在尝试将结果的 url 从数据库传递给函数,创建一个新的 img 元素,并将传递的 url 附加到新创建的 img 标签的 src 属性中。 到目前为止,这似乎有效 - 当我 console.log 结果时,我得到了 &lt;img&gt; 标签的负载,所有标签都附有相应的 src。

不过,我在将这些返回到前端时遇到了麻烦。

我下面的代码显示了循环通过的 php 部分,然后是它在每个循环中调用的 javascript 函数。

    public function getResultsHtml($page, $pageSize, $term) 
        $fromLimit = ($page - 1) * $pageSize;
        $query = $this->con->prepare("SELECT * FROM images 
            WHERE (title LIKE :term
            OR alt LIKE :term) AND broken=0
            ORDER BY clicks DESC
            LIMIT :fromLimit, :pageSize");

        $searchTerm = "%" . $term . "%";
        $query->bindParam(":term", $searchTerm);
        $query->bindParam(":fromLimit", $fromLimit, PDO::PARAM_INT);
        $query->bindParam(":pageSize", $pageSize, PDO::PARAM_INT);
        $query->execute();

        $resultsHtml = "<div class='image-results'>";

        $count = 0;
        while($row = $query->fetch(PDO::FETCH_ASSOC)) 
            $count++;
            $id = $row["id"];
            $imgUrl = $row["imgUrl"];
            $siteUrl = $row["siteUrl"];             
            $title = $row["title"];
            $alt = $row["alt"];

            if($title)
                $displayText = $title;
             else if ($alt) 
                $displayText = $alt;
             else 
                $displayText = $imgUrl;
            

            $resultsHtml .= "<div class='grid-item image$count'>
                                <a href='$imgUrl'>
                                    <script>
                                        document.addEventListener('DOMContentLoaded', function() 
                                            loadImage(\"$imgUrl\", \"image$count\");
                                        );
                                    </script>
                                    <span class='details'>$displayText</span>
                                </a>

                            </div>";
            
            $resultsHtml .= "</div>";
            return $resultsHtml;
        

    var loadImage = function(src, className)

        var image = document.createElement("img");
        var aTag = document.querySelectorAll("." + className + " a");

        image.onload = function()
            aTag.innerHTML = image;
        ;
        image.onerror = function()

        ;

            image.setAttribute("src", src);

    

目前我在前端没有得到任何结果。在页面源代码中,我可以看到每个锚标记内部都有脚本标记,它显示了预加载了参数(loadImage(http://www.com, image22))的函数,但实际上并没有从函数中获得返回。

下面用jQuery解决这个问题,但是我真的不想用jQuery!

            function loadImage(src, className) 

                var image = $("<img>");

                image.on("load", function() 
                    $("." + className + " a").append(image);
                );

                image.on("error", function() 

                );

                image.attr("src", src);

            

我知道用.innerHTML动态写入&lt;script&gt;标签会有些麻烦,但我认为这不是问题,因为脚本标签是在调用函数之前编写的。

我想我有一些东西以错误的顺序触发,或者我错过了 jQuery 使用 .append 函数自动处理的东西。

我也试过aTag.appendChild(image);,也没有结果。

我已经使用 jQuery 几个月了,但我正在尝试彻底学习 Vanilla JS - 我试图掌握 jQuery 函数的实际工作原理,而不是盲目地依赖它们。

非常感谢任何帮助!

【问题讨论】:

你有没有在一切之前预定义$resultsHtml = '';之类的东西? 我做到了! $resultsHtml = "&lt;div class='image-results'&gt;"; 就在$count = 0; 的上方。我有一个几乎重复的 PHP 文件在做同样的事情,但它只是从数据库中读取文本并将其输出到 DOM - 我只是遇到了这个问题,因为循环中的 &lt;script&gt; 元素! 嗯,好的。好吧,如果这是一个 JS 问题,我不是这个人。给出了答案,试一试。 我现在去看看 - 还是谢谢你!为了您的兴趣,我还编辑并附加了整个功能! 哈哈没关系。反正谁需要名声…… 【参考方案1】:

注意querySelectorAll() 返回一个类似数组的 NodeList (https://developer.mozilla.org/en-US/docs/Web/API/NodeList),所以它应该是这样的:

(如果你只想要一个元素返回用户querySelector(),那么你不需要循环)

function loadImage(src, className) 
  var image = document.createElement("img");
  image.src = src;
  image.onload = function() 
    var tags = document.querySelectorAll("." + className + " a");
    for (var i = 0; i < tags.length; i++) 
      tags[i].appendChild(image);
    
  
<div class='grid-item image2'>
  <a href='https://cdn.pixabay.com/photo/2015/08/21/21/55/star-wars-899693_960_720.jpg'>
    <script>
      document.addEventListener('DOMContentLoaded', function()    loadImage("https://cdn.pixabay.com/photo/2015/08/21/21/55/star-wars-899693_960_720.jpg", "image2");
          );
    </script>
    <span class='details'>Star Wars 1</span>
  </a>

</div>

【讨论】:

其实它返回的是一个类似数组的对象,而不是一个数组。 嗯,将querySelectorAll 更改为querySelector 解决了问题,现在它可以按预期运行。我的印象是 querySelector 只会定位页面上的第一个 &lt;a&gt; - 我没有考虑到 className 给它一个唯一的标识符!谢谢你的回答!【参考方案2】:

问题在于您使用的是querySelectorAll,它返回NodeList 而不是单个DOM 节点。这意味着,您必须遍历 NodeList 并将图像附加到其中的所有节点。为此,您可以为每个要插入图像的位置创建新副本,或多次使用cloneNode

var each = function (xs, func) 
  for (var i = 0; i < xs.length; i += 1) 
    func(xs[i]);
  
  return xs;



var loadImage = function(src, className)

    var image = document.createElement("img");
    var aTag = document.querySelectorAll("." + className + " a");

    image.onload = function()
      each(aTag, function (a) 
        a.appendChild(image.cloneNode());
      );
    ;
    image.onerror = function();
    image.alt = '';
    image.src = src;





loadImage('http://www.fillmurray.com/500/300', 'wrap')
<div class="wrap">
  <a href="#"></a>
  <a href="#"></a>
  <a href="#"></a>
</div>

【讨论】:

感谢您的回答!这正是问题所在 - 在过去的几个小时里,我被甩了出去,因为我认为 querySelector 只会针对页面上的第一个 &lt;a&gt;..

以上是关于通过 PHP 循环动态添加 <img> 标记,通过在每个循环上调用 JavaScript 函数的主要内容,如果未能解决你的问题,请参考以下文章

使用 PHP 生成 SVG 文件

php匹配<img/>,添加width,height

使用 PHP 为每个 img 添加父级

如何使用PHP给html<img>标签添加<div>?

如何在 jQuery 中隐藏循环元素

js如何动态添加onclick。