






















文本框中onblur事件,实现用户输入完成后,光标离开文本框实现即时更新。
但是,用户只要用鼠标点击文本框离开后,它均会执行更新操作,文本框内容是否有变化都会进行。
这是一种不好的性能影响。
先示例,然后看看Insus.NET怎样去解决它的。
数据还是使用下面随笔中的数据表,存储过程等。为了能看到效果,在数据表中添加一个字段,UpdatedDate来记录更新时间。
修改表:

ALTER TABLE [dbo].[ZTestData] ADD [UpdatedDate] DATETIME NOT NULL DEFAULT(GETDATE()) GO
View Code
修改更新的存储过程:

ALTER PROCEDURE [dbo].[usp_ZTestData_UpdateBeiZhu] @ID INT, @BeiZhu NVARCHAR(30) AS BEGIN UPDATE [dbo].[ZTestData] SET [BeiZhu] = @BeiZhu, [UpdatedDate] = GETDATE() WHERE [ID] = @ID END GO
View Code
修改获取记录的存储过程:

ALTER PROCEDURE [dbo].[usp_ZTestData_SelectAll] AS BEGIN SELECT [ID], [IMT_pz], [IMT_gx], [BeiZhu], [UpdatedDate] FROM [dbo].[ZTestData] END GO
View Code
此篇随笔,演示示例,由GridView改为html table呈现,

<form id="form1" runat="server"> <div> <table> <thead> <tr> <td>ID</td> <td>Remarks</td> <td>Update Time</td> </tr> </thead> <tbody > <tr> <td> <%# Eval("ID") %> <input id="HiddenID" type="hidden" value=' <%# Eval("ID") %>' /> </td> <td> <input id="TextBeiZhu" type="text" value='<%# Eval("BeiZhu") %>' onblur="update(event);" /> </td> <td> <%# Eval("UpdatedDate") %> </td> </tr> </tbody> <tfoot> </tfoot> </table> </div> <asp:Button ID="ButtonRefreshData" runat="server" Text="RefreshData" Style="display:none" OnClick="ButtonRefreshData_Click" /> </form>
View Code
cs后端对html table数据绑定,

public object DataItem { get; set; } protected void Page_Load(object sender, EventArgs e) { if (!IsPostBack) { Data_Binding(); } } private void Data_Binding() { ZTestDataEntity ztde = new ZTestDataEntity(); DataView dv = ztde.Get_DataTable_GetData().DefaultView; dv.RowFilter = "ID = 2"; //指定记录主键,只是为了演示。 DataItem = dv.ToTable().DefaultView[0]; DataBind(); }
View Code
宣告一个对象object(第1个红色感叹号)。
第2处注意的地方,ztde.Get_DataTable_GetData()返回的是DataTable。
把它转为DefaultView后,可以对从数据库得到数据进行RowFilter过滤。过滤条件你可以自定。
还有一行是dv.ToTable().DefaultView[0];
给它一个0索引。受到过滤条件影响,有时也许返回不一定是1条记录。
最后是html input的text的 onblur="update(event);"事件,
照搬随笔最初参考随笔的链接的写法(不过仍有一些细节修改而变化):

<script src="Scripts/axios.min.js"></script>
<script type="text/javascript">
//onblur事件
function update(event) {
updateBeizhuByTextBox(event.target)
.catch(console.warn);
}
function updateBeizhuByTextBox(txtboxElement) {
return new Promise((resolve, reject) => {
let url = '/api/MyTest/UpdateBeiZhu';
var postData = {
ID: HiddenID.value,
BeiZhu: txtboxElement.value.trim()
};
axios.post(url, JSON.stringify(postData), {
headers: { 'Content-Type': 'application/json; charset=utf-8' }
})
.then(response => {
if (!response.data.Status) {
alert(response.data.Message);
reject(response.data.Message);
} else {
alert(response.data.Message);
resolve(response.data);
}
})
.catch(error => {
console.error(error);
reject(error);
})
.finally(() => {
refreshData();
});
});
}
function refreshData() {
document.getElementById('<%= ButtonRefreshData.ClientID %>').click();
}
</script>
View Code
在#95行代码是为刷新呈现的数表而已。
从效果中看到,内容无变化,它更新了。
如何解决它呢?Insus.NET想到2种方法:
从数据端入手,写个INSTEAD OF UPDATE触发器,

SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO -- ============================================= -- Author: leo yeung -- Create date: 2026-04-30 -- Description: 更新备注前验证是否有变化 -- ============================================= CREATE TRIGGER [dbo].[tri_ZTestData_UpdateBeiZhu] ON [dbo].[ZTestData] INSTEAD OF UPDATE AS BEGIN SET NOCOUNT ON; IF NOT EXISTS ( SELECT 1 FROM inserted i INNER JOIN deleted d ON (i.[ID] = d.[ID] AND i.[BeiZhu] = d.[BeiZhu] )) BEGIN UPDATE target SET [IMT_pz] = i.[IMT_pz], [IMT_gx] = i.[IMT_gx], [BeiZhu] = i.[BeiZhu], [UpdatedDate] =i.[UpdatedDate] FROM [dbo].[ZTestData] target INNER JOIN inserted i ON target.[ID] = i.[ID]; END ELSE BEGIN RAISERROR(N'备注内容无任何变化,更新略过。',16,1) END END GO
View Code

ALTER PROCEDURE [dbo].[usp_ZTestData_UpdateBeiZhu] @ID INT, @BeiZhu NVARCHAR(30) AS BEGIN IF NOT EXISTS ( SELECT 1 FROM [dbo].[ZTestData] WHERE [ID] = @ID AND[BeiZhu] = @BeiZhu ) BEGIN UPDATE [dbo].[ZTestData] SET [BeiZhu] = @BeiZhu, [UpdatedDate] = GETDATE() WHERE [ID] = @ID END ELSE BEGIN RAISERROR(N'备注内容无任何变化,更新略过。',16,1) RETURN END END GO
View Code

window.lastSavedData = window.lastSavedData || new Map(); function updateBeizhuByTextBox(txtboxElement) { return new Promise((resolve, reject) => { var uniqueKey = txtboxElement.id + '_' + HiddenID.value.trim(); var newValue = txtboxElement.value.trim(); // 检查是否与上次成功保存的值相同 var lastValue = window.lastSavedData.get(uniqueKey); if (lastValue === newValue) { console.log("内容未改变,无需保存", uniqueKey, newValue); return resolve("内容未改变"); } let url = '/api/IMT/UpdateBeiZhu'; var postData = { ID: HiddenID.value, BeiZhu: newValue }; axios.post(url, JSON.stringify(postData), { headers: { 'Content-Type': 'application/json; charset=utf-8' } }) .then(response => { if (response.data.Status !== true && response.data.Status !== "true") { alert(response.data.Message); reject(response.data.Message); } else { alert(response.data.Message); window.lastSavedData.set(uniqueKey, newValue); console.log("已记录", uniqueKey, newValue); resolve(response.data); } }) .catch(error => { console.error(error); alert("保存失败,请重试!", true); reject(error); }) .finally(() => { // }); }); }
View Code
这样一改,可以防止同一文本框第2次更新时,不会去呼叫Web API把数据上传至数据库进行更新。
虽然不是很完善,已经做出很大改善了。
是否有更好方案?期待......
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。