jquery DOM元素渲染完成后如何操作

oogrdqng  于 2023-08-04  发布在  jQuery
关注(0)|答案(1)|浏览(184)

我使用js和jQuery来处理表单元素
此表单用于编辑
它从后端获取数据,然后运行顺序函数来显示数据:
1-单击手动单选按钮(显示新标题字段和源标题选择框以及类型复选框)
2-填写新标题输入字段
3-选择源头(这将带来源头的唯一值,并为每个值生成两个输入(一个用于旧值,第二个用于新值))
4-选择类型(手动(将新值从选择转换为输入)或MRSH(将新值从输入转换为选择))
5-将来自服务器的数据填充到输入框或选择框中。
问题出在最后一步(它不能正常工作,因为前面的步骤可能需要一些时间来渲染)
代码如下:

/**
     * Handle Edit Header in case of Manual
     * @param {Object} headerData
     * @param {string} columnName
     * @returns {void}
     */
    function handleEditManual(headerData, columnName) {
        $("#manual").click();

        // Set Column Name Field
        $("#column-name").val(columnName);

        // Set the Type according to the incoming type
        let values = headerData.values;

        addMappingPart(headerData).then(addInputsOrSelects(headerData)).then(function () {
            switch (mode) {
                case "manual":
                    fillInputFields(values);
                    break;

                case "MRSH":
                    fillSelectBoxes(values);
                    break;
            }
        });
    }

    // Step 2: Fill input fields
    function fillInputFields(values) {
        $(".source-inputs").each(function () {
            let sourceValue = $(this).data("value");
            let manualValue =
                values.find((value) => value.value === sourceValue).then ??
                null;
            $(this).next().find("input").val(manualValue);
        });
    }

    // Step 2: Fill input fields
    function fillSelectBoxes(values) {
        $(".source-inputs").each(function () {
            let sourceValue = $(this).data("value");
            let mrsvId =
                values.find((value) => value.value === sourceValue).id ?? null;
            $(this).next().find("select").val(mrsvId).trigger("change");
        });
    }

    function addMappingPart(headerData) {
        let sourceHeader = headerData.source_header;

        return new Promise(function (resolve) {
            $("#source-header").val(sourceHeader).trigger("change");

            // Resolve the Promise to signal completion of Step 1
            resolve();
        });
    }

    function addInputsOrSelects(headerData) {
        let type = headerData.type ? true : false;
        let mrshId = headerData.mrsh_id ?? null;

        return new Promise(function (resolve) {
            // Simulate some time to add input fields
            if (type) {
                $("#type-switch").click();
                mode = "MRSH";

                // Set the MRSH if the Type is MRSH
                $("#select-mrsh").val(mrshId).trigger("change");
            } else {
                mode = "manual";
            }

            // Resolve the Promise to signal completion of Step 1
            resolve();
        });
    }

字符串


的数据

w3nuxt5m

w3nuxt5m1#

您的尝试中存在一些问题:

  • .then(addInputsOrSelects(headerData))不会向.then传递回调函数,而是立即 * 执行 * addInputsOrSelects。并且它返回的promise作为.then()的参数没有用。
  • 在使用new Promise创建新promise的地方,立即(同步)解析它们:这意味着将不存在用于异步UI相关更新的空间。在promise构造函数回调中同步调用resolve几乎没有什么用处。

在继续编写更多代码之前完成所有渲染的解决方案是依赖于requestAnimationFrame。传递给此函数的回调将在下一个绘制周期发生(更新屏幕)之前执行,如果该回调也调用requestAnimationFrame,则此处给出的回调将仅在一个绘制周期之后执行。这个函数可以很容易地实现,以便您可以将then链接到它或将它与await组合。
我稍微修改了一下你的代码,在每次调用triggerclick之后添加一个await,它允许发生绘制周期:

// Promisified requestAnimationFrame:
const justBeforePaint = () => new Promise(requestAnimationFrame);

/**
 * Handle Edit Header in case of Manual
 * @param {Object} headerData
 * @param {string} columnName
 * @returns {void}
 */
async function handleEditManual(headerData, columnName) {
    await justBeforePaint(); // Await this immediately before doing anything else
    
    $("#manual").click();
    await justBeforePaint(); 

    // Set Column Name Field
    $("#column-name").val(columnName);

    // Set the Type according to the incoming type
    const values = headerData.values;
    addMappingPart(headerData);  
    await justBeforePaint();

    const mode = await addInputsOrSelects(headerData);
    switch (mode) {
    case "manual":
        fillInputFields(values);
        break;
    case "MRSH":
        fillSelectBoxes(values);
        break;
    }
    await justBeforePaint();
}

// Step 2: Fill input fields
function fillInputFields(values) {
    $(".source-inputs").each(function () {
        let sourceValue = $(this).data("value");
        let manualValue =
            values.find((value) => value.value === sourceValue).then ??
            null;
        $(this).next().find("input").val(manualValue);
    });
}

// Step 2: Fill input fields
function fillSelectBoxes(values) {
    $(".source-inputs").each(function () {
        const sourceValue = $(this).data("value");
        const mrsvId =
            values.find((value) => value.value === sourceValue).id ?? null;
        $(this).next().find("select").val(mrsvId).trigger("change");
    });
}

function addMappingPart(headerData) {
    const sourceHeader = headerData.source_header;
    $("#source-header").val(sourceHeader).trigger("change");
}

async function addInputsOrSelects(headerData) {
    const mrshId = headerData.mrsh_id ?? null;
    if (headerData.type) {
        $("#type-switch").click();
        await justBeforePaint();
        // Set the MRSH if the Type is MRSH
        $("#select-mrsh").val(mrshId).trigger("change");
        await justBeforePaint();
        return "MRSH";
    } else {
        return "manual";
    }
}

字符串
有些justBeforePaint调用可能不是必需的--这取决于这些trigger()click()调用究竟异步执行什么,以及其余代码是否依赖于此。

相关问题