You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Javascript控件无法识别编辑状态问题求助

表单控件编辑状态判断失效问题解决

我有一个简易表单控件,规则为:若用户已编辑字段,则不从数据库更新该字段并标记;若未编辑,则从数据库获取最新值更新控件。目前该逻辑失效,约半数情况用户编辑后控件仍被数据库值覆盖。

相关代码

生成控件的代码

控件通过ViewModel的foreach动态生成:

@foreach (var row in Model.controls)
{
  <input type="text" name="@row.Name" id="@row.NameID" value="@row.Value" edited="0" class="form-control data-field" onfocus="return ControlEdited(this.id)" style="width: 300px" />
}

控件焦点触发的标记函数

function ControlEdited(id) {
    document.getElementById(id).setAttribute('edited', 1);
    document.getElementById(id).style.backgroundColor = "yellow";
}

核心问题函数UpdateControls

该函数本应仅更新未编辑字段,但时常失效覆盖已编辑内容:

function UpdateControls() {
    $(".data-field").each(function () {
        var nameAttr = $(this).attr('name');
        var id = $(this).attr('id');
        var edited = $(this).attr('edited');
        var stationID = document.getElementById('stationDD').value;

        if (edited == 0) {
            var url = "/Manager/UpdateControlsFromDB/";
            $.ajax({
                url: url,
                data: { name: nameAttr, station: stationID },
                cache: false,
                type: "POST",
                success: function (data) {
                    if (data != null) {
                        document.getElementById(id).value = data;
                    }
                },
                error: function (response) {
                    alert("Issue updating the page controls from database. Information: " + response.responseText);
                }
            });
        } else {
            // 用户已编辑,不更新
        }
    });
}

问题根源分析

  1. AJAX异步竞态问题:判断edited状态是在发起AJAX请求前完成的,但请求是异步的。如果用户在请求发起后、响应返回前点击控件将edited设为1,回调依然会执行更新,因为状态判断没有在回调阶段重新校验。
  2. onfocus标记不准确:onfocus仅标记用户获得焦点,但用户可能获取焦点后未编辑就离开,此时不该阻止更新;反之,若用户在焦点触发后编辑,异步请求的响应可能仍会覆盖内容。
  3. 自定义属性类型隐患:edited是DOM字符串属性,使用==弱等于判断可能出现类型匹配问题(比如字符串"0"和数字0比较没问题,但如果属性值异常会导致判断失效)。

解决方案

1. 回调阶段重新校验状态

在AJAX成功回调中再次检查控件的edited状态,确保更新时控件确实未被编辑:

function UpdateControls() {
    $(".data-field").each(function () {
        var $control = $(this);
        var nameAttr = $control.attr('name');
        var id = $control.attr('id');
        var stationID = $('#stationDD').val();

        var url = "/Manager/UpdateControlsFromDB/";
        $.ajax({
            url: url,
            data: { name: nameAttr, station: stationID },
            cache: false,
            type: "POST",
            success: function (data) {
                if (data != null) {
                    var $target = $('#' + id);
                    // 回调时重新校验状态,用字符串严格匹配避免类型问题
                    if ($target.attr('edited') === "0") {
                        $target.val(data);
                    }
                }
            },
            error: function (response) {
                alert("Issue updating the page controls from database. Information: " + response.responseText);
            }
        });
    });
}

2. 改用oninput标记真实编辑行为

把onfocus换成oninput,只有用户真正输入内容时才标记为已编辑,避免误标记:

@foreach (var row in Model.controls)
{
  <input type="text" name="@row.Name" id="@row.NameID" value="@row.Value" edited="0" class="form-control data-field" oninput="ControlEdited(this.id)" style="width: 300px" />
}

3. 使用jQuery data()存储状态(更可靠)

放弃自定义DOM属性,用data()存储编辑状态,避免字符串类型问题:

// 页面加载时初始化状态
$(function() {
    $(".data-field").data('edited', 0);
});

function ControlEdited(id) {
    $('#' + id).data('edited', 1).css('backgroundColor', 'yellow');
}

function UpdateControls() {
    $(".data-field").each(function () {
        var $control = $(this);
        var nameAttr = $control.attr('name');
        var id = $control.attr('id');
        var stationID = $('#stationDD').val();

        $.ajax({
            url: "/Manager/UpdateControlsFromDB/",
            data: { name: nameAttr, station: stationID },
            cache: false,
            type: "POST",
            success: function (data) {
                if (data != null) {
                    var $target = $('#' + id);
                    if ($target.data('edited') === 0) {
                        $target.val(data);
                    }
                }
            },
            error: function (response) {
                alert("Issue updating the page controls from database. Information: " + response.responseText);
            }
        });
    });
}

4. 可选:添加AJAX请求取消机制

如果UpdateControls会被频繁调用,可取消未完成的旧请求,避免旧响应覆盖新状态:

var controlRequests = {};

function UpdateControls() {
    $(".data-field").each(function () {
        var $control = $(this);
        var id = $control.attr('id');
        var nameAttr = $control.attr('name');
        var stationID = $('#stationDD').val();

        // 取消当前控件未完成的旧请求
        if (controlRequests[id]) {
            controlRequests[id].abort();
        }

        controlRequests[id] = $.ajax({
            url: "/Manager/UpdateControlsFromDB/",
            data: { name: nameAttr, station: stationID },
            cache: false,
            type: "POST",
            success: function (data) {
                delete controlRequests[id];
                if (data != null) {
                    var $target = $('#' + id);
                    if ($target.data('edited') === 0) {
                        $target.val(data);
                    }
                }
            },
            error: function (response) {
                delete controlRequests[id];
                alert("Issue updating the page controls from database. Information: " + response.responseText);
            }
        });
    });
}

内容的提问来源于stack exchange,提问作者Eli

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.16 07:23:05