
在使用Bootstrap模态窗口(Modal)结合文件上传库(如Dropzone.js)时,一个常见需求是根据用户点击的不同上传按钮,向Dropzone提供不同的上传目标URL或其他动态参数。
最初的尝试可能是在模态窗口的 shown.bs.modal 事件中获取这些参数。然而,shown.bs.modal 事件的 e.currentTarget 始终指向模态窗口本身,而非触发该模态窗口的原始按钮。这意味着在 shown.bs.modal 回调中,我们无法直接通过 e.currentTarget 向上或向下遍历DOM来找到是哪个具体的上传按钮触发了模态,从而也就无法获取与该按钮关联的动态 data-action_url。当页面存在多个上传按钮,每个按钮需要不同的上传路径时,这个问题尤为突出。
例如,以下代码片段展示了这种尝试的局限性:
// 假设在 shown.bs.modal 事件中尝试获取
this.$body.on('shown.bs.modal', this.$modalId, this.functions.openUploadFilesModal.bind(this));
openUploadFilesModal: function (e) {
// 这里的 e.currentTarget 是模态窗口本身,无法追溯到点击的按钮
let dropzoneParamEl = $(e.currentTarget).closest('.field_form').find('.dz_params_item'); // 结果可能为 undefined
let action_url = $(dropzoneParamEl).attr('data-action_url'); // 结果为 undefined
// ...
}解决此问题的核心思路是:将获取动态数据的逻辑放在触发模态窗口的点击事件中。这样,e.currentTarget 将正确指向被点击的上传按钮,从而可以方便地获取与其相关的动态数据。获取数据后,再手动调用Bootstrap的API来显示模态窗口。
首先,确保你的HTML结构能够清晰地将上传按钮与它的动态参数关联起来。我们使用 data-action_url 属性来存储上传URL。
<div class="form-group">
<div class="field">
<label>Photos</label>
<div class="field_info" data-field_photo_id="5">
<div class="value" data-item_id=""></div>
</div>
<div class="field_form">
<!-- 上传按钮,移除 data-toggle="modal" 属性,由JS手动控制 -->
<a class="btn btn-dark btn-md btnUpload" href="#" data-target="#modal-upload">
<i class="fa fa-cloud-upload"></i> Upload
</a>
<!-- 包含动态参数的元素 -->
<div class="dz_params_item"
data-entity_id="<?=$item->request_id?>"
data-action_url="/files/upload/<?=$item->request_id?>"
></div>
</div>
</div>
</div>
<!-- 模态窗口定义 -->
<div class="modal fade" id="modal-upload" tabindex="-1" role="dialog" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered" role="document">
<div class="modal-content">
<div class="modal-header">
<h4 class="modal-title">
Upload files
</h4>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true"><i class="fal fa-times"></i></span>
</button>
</div>
<div class="modal-body">
<!-- Dropzone 容器 -->
<div id="filesDropzone"></div>
</div>
</div>
</div>
</div>注意: 上传按钮 <a> 标签上的 data-toggle="modal" 属性已被移除。模态窗口的显示将完全由JavaScript控制。
我们将创建一个$.dispatcherFiles 对象来封装所有相关逻辑,包括DOM缓存、事件绑定和核心功能函数。
(function( $ ){
// 模块级变量,用于存储模态ID、Dropzone实例等
let $modalId = '#modal-upload';
let $filesDropzone = null; // 用于存储当前的Dropzone实例
let $parallelUploads = 100;
let $maxFiles = 10;
let $files = []; // 如果需要跟踪上传文件
$.dispatcherFiles = {
// 缓存DOM元素,提高性能
cacheDom: function(){
this.$body = $('body');
},
// 核心功能函数
functions: {
// 当上传按钮被点击时触发
uploadFilesModal: function (e) {
// 阻止默认的链接行为,如果按钮是 <a> 标签
e.preventDefault();
// 获取触发点击事件的按钮元素
let clickedButton = $(e.currentTarget);
// 从点击的按钮向上查找最近的 .field_form 容器
// 再从 .field_form 容器向下查找 .dz_params_item 元素
let dropzoneParamEl = clickedButton.closest('.field_form').find('.dz_params_item');
// 获取 data-action_url 属性值
let action_url = dropzoneParamEl.attr('data-action_url');
// 打印调试信息,确认获取到正确的值
console.log("Clicked button:", clickedButton);
console.log("Associated parameters element:", dropzoneParamEl);
console.log("Action URL:", action_url);
// 检查是否已存在Dropzone实例,如果存在则销毁,确保每次打开模态都是新的实例
if ($filesDropzone) {
$filesDropzone.destroy();
$filesDropzone = null; // 清空引用
}
// 初始化 Dropzone 之前,确保容器元素存在且可见
// 将 Dropzone 容器添加 'dropzone' 类
$($modalId + ' #filesDropzone').addClass('dropzone');
// 初始化 Dropzone 实例
$filesDropzone = new Dropzone($modalId + ' #filesDropzone', { // 针对模态内的特定ID
url: action_url, // 使用动态获取的URL
uploadMultiple: true,
parallelUploads: $parallelUploads,
maxFiles: $maxFiles,
autoProcessQueue: true, // 自动处理上传队列
});
// 绑定 Dropzone 事件处理器
$filesDropzone.on('error', function(file, message, xhr) {
console.error('Dropzone Error:', message);
// $(that.$modalId).modal('hide'); // 根据需求决定是否隐藏模态
alert('文件上传失败: ' + message);
});
$filesDropzone.on('success', function(file, response) {
console.log('文件上传成功:', file, response);
// $(that.$modalId).modal('hide'); // 根据需求决定是否隐藏模态
// 在这里处理上传成功后的逻辑,例如更新页面内容
});
$filesDropzone.on('complete', function(file) {
// 当文件上传完成(无论成功或失败)时触发
// 可以选择在这里移除文件缩略图等
// $filesDropzone.removeFile(file);
});
$filesDropzone.on('queuecomplete', function() {
// 当所有文件上传完成时触发
$($modalId).modal('hide'); // 所有文件上传完毕后隐藏模态
});
// 手动显示模态窗口
$($modalId).modal('show');
},
// 当模态窗口隐藏时触发,用于清理 Dropzone 实例
hideUploadFilesModal: function (e) {
if ($filesDropzone) {
$filesDropzone.destroy(); // 销毁 Dropzone 实例
$filesDropzone = null; // 清空引用
// 移除 dropzone 类,以备下次重新初始化
$($modalId + ' #filesDropzone').removeClass('dropzone dz-started');
// 清除 Dropzone 容器中的内容,防止残留
$($modalId + ' #filesDropzone').empty();
}
},
},
// 事件绑定
events: function(){
// 绑定点击事件到所有具有 .btnUpload 类的按钮
this.$body.on('click', '.btnUpload', this.functions.uploadFilesModal.bind(this));
// 绑定模态窗口隐藏事件,用于清理资源
this.$body.on('hidden.bs.modal', $modalId, this.functions.hideUploadFilesModal.bind(this));
},
// 初始化函数
init: function () {
this.cacheDom();
this.events();
}
};
// 启动 $.dispatcherFiles 模块
$.dispatcherFiles.init();
})(jQuery);为了方便测试,以下是一个完整的HTML文件,包含了所有必要的库和上述JavaScript逻辑:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>动态获取模态窗口上传URL</title>
<!-- Bootstrap CSS -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.3.0/css/bootstrap.min.css" integrity="sha512-t4GWSVZO1eC8BM339Xd7Uphw5s17a86tIZIj8qRxhnKub6WoyhnrxeCIMeAqBPgdZGlCcG2PrZjMc+Wr78+5Xg==" crossorigin="anonymous" referrerpolicy="no-referrer" />
<!-- Font Awesome CSS -->
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.3.0/css/font-awesome.css" rel="stylesheet" type='text/css'>
<!-- Dropzone CSS -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/dropzone/5.9.3/dropzone.min.css" integrity="sha512-U2WE1ktpMTuRBPoCFDzomoIorbOyUv0sP8B+INA3EzNAhehbzED1rOJg6bCqPf/Tuposxb5ja/MAUnC8THSbLQ==" crossorigin="anonymous" referrerpolicy="no-referrer" />
<style>
body {
padding: 20px;
}
.field {
margin-bottom: 30px;
padding: 15px;
border: 1px solid #eee;
border-radius: 5px;
background-color: #f9f9f9;
}
.field_form {
margin-top: 10px;
}
.dz_params_item {
display: none; /* 隐藏参数元素 */
}
#filesDropzone {
min-height: 150px;
border: 2px dashed #0087F7;
border-radius: 5px;
background: white;
padding: 20px;
text-align: center;
font-size: 1.2em;
color: #ccc;
}
#filesDropzone.dropzone-previews {
border: none;
background: transparent;
}
</style>
</head>
<body>
<div class="container">
<h1>文件上传管理</h1>
<div class="form-group">
<div class="field">
<label>图片上传 (产品A)</label>
<div class="field_info" data-field_photo_id="5">
<div class="value" data-item_id=""></div>
</div>
<div class="field_form">
<a class="btn btn-dark btn-md btnUpload" href="#" data-target="#modal-upload">
<i class="fa fa-cloud-upload"></i> 上传产品A图片
</a>
<div class="dz_params_item"
data-entity_id="product_A"
data-action_url="/files/upload/product_A"
></div>
</div>
</div>
</div>
<div class="form-group">
<div class="field">
<label>图片上传 (产品B)</label>
<div class="field_info" data-field_photo_id="6">
<div class="value" data-item_id=""></div>
</div>
<div class="field_form">
<a class="btn btn-dark btn-md btnUpload" href="#" data-target="#modal-upload">
<i class="fa fa-cloud-upload"></i> 上传产品B图片
</a>
<div class="dz_params_item"
data-entity_id="product_B"
data-action_url="/files/upload/product_B"
></div>
</div>
</div>
</div>
<div class="form-group">
<div class="field">
<label>图片上传 (用户头像)</label>
<div class="field_info" data-field_photo_id="7">
<div class="value" data-item_id=""></div>
</div>
<div class="field_form">
<a class="btn btn-dark btn-md btnUpload" href="#" data-target="#modal-upload">
<i class="fa fa-cloud-upload"></i> 上传用户头像
</a>
<div class="dz_params_item"
data-entity_id="user_avatar"
data-action_url="/files/upload/user_avatar"
></div>
</div>
</div>
</div>
</div>
<!-- 模态窗口定义 -->
<div class="modal fade" id="modal-upload" tabindex="-1" role="dialog" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered" role="document">
<div class="modal-content">
<div class="modal-header">
<h4 class="modal-title">
上传文件
</h4>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<div id="filesDropzone">
<p>将文件拖放到此处,或点击上传。</p>
</div>
</div>
</div>
</div>
</div>
<!-- jQuery -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
<!-- Bootstrap JS -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.3.0/js/bootstrap.bundle.min.js" integrity="sha512-wV7YjLCoNrWlEJMlnWGjOqfRPIB84YxY4y7tP7f7Q7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f以上就是从模态窗口触发元素获取动态数据:Dropzone上传URL配置指南的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号