多个动态初始化时只有一个 Dropzone 工作

Only one Dropzone working when multiple dinamically initialized

我正在编写一个 Web 应用程序,我需要根据服务器内容初始化多个 dropzones,我目前有一个类似于这样的代码:

<script src="/js/dropzone.min.js"></script>
<script>
Dropzone.autoDiscover = false;
window.dropzones = {};


function checkDropzones(container) {
    var possibleDropzones = container.querySelectorAll('.needs-to-be-dropzoned');
    possibleDropzones.forEach(function (zone) {
        if (zone.id.length === 0) {
            zone.id = 'dropzone_filled_' + (new Date()).getTime();
            window.dropzones[zone.id] = new Dropzone(
                '#' + zone.id,
                {
                    paramName: 'image',
                    addRemoveLinks: true,
                }
            );
        }
    })
}

function renderServerContent() {
    window.customSections.forEach(function (custom_section) {
        var container = document.getElementById(custom_section);
        $.ajax({
            method: 'GET',
            url: '/customRenderUrl?section=' + custom_section,
            headers: {
                Accept: 'application/json',
                'Content-Type': 'application/json'
            },
            success: function (response) {
                container.innerHTML = container.innerHTML + response.component;
                if (response.component_type === 'image_uploader') {
                    checkDropzones(container);
                }
                // ... other marginal stuff ... 
            },
            dataType: 'json'
        })
    })
}

// ... other scripts ... 

window.customSections = [/* server stuff */];
renderServerContent();
</script>

基本上,我有一些东西要从服务器动态呈现,所以我发送一个请求来询问组件呈现的数据,当我得到答复时,我检查插入的内容是否包含带有 [=13 的元素=],如果是这样,我为其分配一个基于时间的 ID(组件渲染在每个组件之间有延迟,因此 ID 是唯一的)并实例化 dropzone。这仅适用于一个拖放区,但当多个拖放区位于同一页面上时,它不会产生错误,但仅适用于页面上的最后一个元素。

服务器内容是这样的:

<form
    class="col-12 container-fluid pb-2 dropzone needs-to-be-dropzoned"
    method="POST"
    action="/imageUploadUrl"
>
    <input type="hidden" name="_token" value="..." >

    <div class="dz-default dz-message">
        Upload files
    </div>
    <div class="fallback">
        <input name=image" type="file" />
    </div>
</form>

如果我启动 console.dir(window.dropzones) 我得到 2 个对象:

Object { dropzone_filled_1624370363574: {…}, dropzone_filled_1624370363803: {…} }
​
dropzone_filled_1624370363574: Object { element: form#dropzone_filled_1624370363574.col-12.container-fluid.pb-2.dropzone.needs-to-be-dropzoned.dz-clickable, version: "5.9.2", clickableElements: (1) […], … }
​
dropzone_filled_1624370363803: Object { element: form#dropzone_filled_1624370363803.col-12.container-fluid.pb-2.dropzone.needs-to-be-dropzoned.dz-clickable, version: "5.9.2", clickableElements: (1) […], … }

我做错了什么或遗漏了什么?

我做了各种尝试来解决这个问题,最后,我通过将所有服务器调用包装到 promises 中来修复它,等待所有 promises 解决,然后才检查 dropzones。代码大概是这样的:

<script src="/js/dropzone.min.js"></script>
<script>
Dropzone.autoDiscover = false;
window.dropzones = {};
window.containersToCheck = [];


function checkDropzones(container) {
    var possibleDropzones = container.querySelectorAll('.needs-to-be-dropzoned');
    possibleDropzones.forEach(function (zone) {
        if (zone.id.length === 0) {
            zone.id = 'dropzone_filled_' + (new Date()).getTime();
            window.dropzones[zone.id] = new Dropzone(
                '#' + zone.id,
                {
                    paramName: 'image',
                    addRemoveLinks: true,
                }
            );
        }
    })
}

function renderServerContent() {
    return new Promise(function(resolve, reject) {
        window.customSections.forEach(function (custom_section) {
            var container = document.getElementById(custom_section);
            $.ajax({
                method: 'GET',
                url: '/customRenderUrl?section=' + custom_section,
                headers: {
                    Accept: 'application/json',
                    'Content-Type': 'application/json'
                },
                success: function (response) {
                    container.innerHTML = container.innerHTML + response.component;
                    if (response.component_type === 'image_uploader') {
                        window.containersToCheck.push(container);
                    }
                    resolve();
                    // ... other marginal stuff ... 
                },
                dataType: 'json'
            })
        })
    });
}

// ... other scripts ... 

window.customSections = [/* server stuff */];
var promises = [];
promises.push(renderServerContent());
// other renderings
Promise.all(promises).then(function (results) {
    window.containersToCheck.forEach(function(container) {
        checkDropzones(container);
    });
})
</script>

这样,所有 Dropzones 都可以工作。