【问题标题】:How to change a specific image in a dynamic table?如何更改动态表中的特定图像?
【发布时间】:2020-03-26 13:57:49
【问题描述】:

我在一张桌子上面临这种奇怪的行为,老实说,我不知道我在这里错过了什么。

我有下表:

<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/

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

【问题讨论】:

  • 看起来你有一个额外的&lt;/td&gt;
  • 谢谢你,罗伯。我只是稍微清理了这段代码,以便更容易理解,并没有注意到这个额外的 。您可以在 JSFiddle 中找到功能齐全的代码。

标签: javascript jquery html dom


【解决方案1】:

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

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 响应加载并添加到文档中的元素。

我建议您改为在 document 上设置一个事件侦听器,并以 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/

关于find的信息:https://api.jquery.com/find/


完整解决方案:

我已将您的小提琴示例分叉为一个工作示例:https://jsfiddle.net/gkthp6qd/

【讨论】:

    【解决方案2】:

    问题是您使用id 作为选择器,即#imagePreview

    尝试改变

    $('#imagePreview').css('background-image', 'url('+e.target.result +')');
    

      $(event.target).parents('.avatar-upload').find('.imagePreview').css('background-image', 'url('+e.target.result +')');
    

    Id 总是返回第一个匹配的元素

    我所做的是,

    捕捉父元素,然后捕捉 imagePreview 元素

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-08-18
      • 1970-01-01
      相关资源
      最近更新 更多