javascript - 如何更改动态表中的特定图像?

标签 javascript jquery html dom

我在一张 table 上遇到了这种奇怪的行为,老实说,我不知道我在这里错过了什么。

我有下表:

<table>
<tr>
    <th>City</th>
    <th>Date</th>
    <th>Description</th>
    <th>Picture</th>
    <th>Sort</th>
    <th>
        <span class="table-add mb-3 mr-2">
          <a href="#!" class="text-success">
             <i class="fas fa-plus fa-2x program" aria-hidden="true"></i>
          </a>
        </span>
    </th>
</tr>
<tr>
    <td>Name</td>
    <td>01-01-20</td>
    <td>Lorem ipsum dolor sit amet.</td>
    <td>
        <div class="container-image">
            <div class="avatar-upload">
                <div class="avatar-edit">
                    <input type='file' id="imageUpload" accept=".png, .jpg, .jpeg" />
                    <label for="imageUpload"></label>
                </div>
                <div class="avatar-preview">
                    <div id="imagePreview" class="imagePreview" style="background-image: url(http://i.pravatar.cc/);">
                    </div>
                </div>
            </div>
        </div>
    </td>
    <td></td>
</tr>

我有一个图标按钮来克隆我的最后一个“tr”并在表格底部创建一个新的。

我还有一个 jquery 函数可以将图像上传到每一行,但由于某种原因,例如当我更改第三行中的图像时,它总是会更新我的第一行。

<script>
function readURL(input) {
    if (input.files && input.files[0]) {
        var reader = new FileReader();
        reader.onload = function(e) {
            $('#imagePreview').css('background-image', 'url('+e.target.result +')');
            $(this).hide();
            $(this).fadeIn(650);
        };
        reader.readAsDataURL(input.files[0]);
    }
}
$("#imageUpload").change(function() {
    readURL(this);
});

我使用我的表的功能示例创建了一个 JSFiddle,以便让您准确了解此问题:https://jsfiddle.net/d95yo4vg/

只需添加一个新行,然后尝试更改第二行的图像。

最佳答案

您的代码存在几个问题。让我们一次一个地浏览它们。

<强>1。单击图片图标标签不会打开正确输入标签的上传对话框

当您添加新行时,您将在 html 中获得这些元素:

<input type='file' id="imageUpload" accept=".png, .jpg, .jpeg" />
<label for="imageUpload"></label>

<input type='file' id="imageUpload" accept=".png, .jpg, .jpeg" />
<label for="imageUpload"></label>

因为我们有多个具有相同值的 id 属性,所以我们违反了 html5 规范: https://html.spec.whatwg.org/multipage/dom.html#the-id-attribute 并且由于有多个输入具有相同的 id,因此两个标签将仅针对第一个输入。因此,即使我们单击第二行中的标签,我们也会继续将文件上传到第一个输入。

您可以通过将标签包裹在输入周围来解决此问题,这样您就不再需要 for 属性:

<label>
  <input />
</label>

<强>2。您仅在页面加载时在输入上添加一个事件监听器 这不是代码中的错误,但这是一个建议,以防您使用 JavaScript 将新元素添加到页面。

$("#imageUpload").change(...)

您正在输入上创建更改事件监听器,但仅在页面加载时创建一次。因此,如果您通过代码添加具有相同元素的新 tr(没有深度克隆),则新行的输入上没有事件监听器。它在您的示例中确实有效,因为您创建了 tr 的深层克隆。但它不适用于从 AJAX 响应加载并添加到文档中的元素。

我建议您在文档上设置一个事件监听器,并以 imageUpload 子项为目标。因为文档将始终存在于网页上,并且始终只有一个。

文档监听器的代码示例:

$(document).on("change", ".imageUpload", function(e) {
  readURL(e.currentTarget);
});

<强>3。在 readURL 函数中,您的目标是第一行中的 imagePreview

此问题与第一个问题的原因相同,但解决方案不同。 我们有多个带有 imagePreview id 的 img。因此 $('#imagePreview') 选择器将仅返回第一行中的 imagePreview。

要选择右行上的 imagePreview,您可以使用 closest() 函数将 dom 向上遍历到该行中的元素。并使用find()函数遍历回imagePeview。一个例子:

$(input).closest('.avatar-upload').find('.imagePreview')

有关最近的信息:https://api.jquery.com/closest/

有关查找的信息:https://api.jquery.com/find/

<小时/>

完整解决方案:

我已将您的 fiddle 示例 fork 为一个工作示例:https://jsfiddle.net/gkthp6qd/

关于javascript - 如何更改动态表中的特定图像?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60868961/

相关文章:

javascript - 用js模拟悬停几个映射的圆形按钮

java - Angular.js 和 Java Applet

javascript - 以pdf格式发送html代码的代码是什么

javascript - 悬停时停止计时器

javascript - HTML5 视频源属性

javascript - 根据提供的数据属性值选择多个tr

javascript - Bootstrap 中的选项卡和药丸

javascript - AJAX 加载后 jQuery Ready 事件不工作

html - 如何使用 emacs org-mode 在导出的 html 文件中包含 svg 图像?

javascript - 如何在 Canvas 上使用 javascript 为圆锥体或圆柱体提供 3d 效果?以及如何在其中填充所需的颜色?