我在一张 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 子项为目标。因为文档将始终存在于网页上,并且始终只有一个。
文档监听器的代码示例:
- 注意 1:我们已经在此处使用类选择器而不是 id 选择器因为第一个问题。
- 注意 2:我们解析 e.currentTarget 而不是 this,因为使用文档选择器,它已更改为 document 而不是 < strong>imageUpload 元素。 (https://developer.mozilla.org/en-US/docs/Web/API/Event/currentTarget)
$(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/