【问题标题】:Return value ignored from Jquery function从 Jquery 函数中忽略的返回值
【发布时间】:2025-12-29 23:40:12
【问题描述】:

我有一块 jQuery 附加到 asp.net 网络表单前端(表单的输入控件用标准的 asp.net AJAX 面板包装),它有一个三个下拉列表,其中有一个附上 jQuery:

$(document).ready(function () {
    jQuery("select").change(function () {
        alert("Hi");
        return false;
    });
});

下拉列表有一个由 ASP.NET 附加的服务器端更改事件,正如您所期望的那样:

<select name="ctl00$leftContent$cmbPressureUnitsPo" tabindex="6" class="unit" id="cmbPressureUnitsPo" onchange="javascript:setTimeout('__doPostBack(\'ctl00$leftContent$cmbPressureUnitsPo\',\'\')', 0)">
            <option value="1">kPag</option>
            <option value="1000">Pag (N/m²)</option>
            <option selected="selected" value="0.001">MPag</option>
            <option value="0.14504">PSIg</option>
            <option value="10">mBarg</option>
            <option value="0.01">Barg</option>
            <option value="0.010197">kgf/cm²</option>
            <option value="0.010197">atg</option>
            <option value="0.0098692">atmg</option>
            <option value="7.5001">torrg (mmHg)</option>
            <option value="101.97">mmH₂O</option>
            <option value="0.29528">inHg</option>

        </select>

唯一的问题是 return false 不会像我期望的那样抑制服务器端事件!如果我实现了一个返回 false 的普通 javascript 函数,那么我错过了什么?

我也试过 event.PreventDefault 没有效果!

【问题讨论】:

    标签: jquery events


    【解决方案1】:

    __doPostBack 方法似乎被包装在绑定到 onchange 处理程序的 setTimeout 中。

    <select ...  onchange="javascript:setTimeout('__doPostBack(\'ctl00$leftContent$cmbPressureUnitsPo\',\'\')', 0)">
    

    您的事件处理程序(通过 jQuery 绑定到 select 元素)将与该事件处理程序分开调用(我之前的猜测是,考虑到 setTimeout 的工作原理 - 但您永远不知道......计时器的怪癖)

    【讨论】:

    • 谢谢 Jack,你说得对,似乎 setTimeout 保证了 DOM 的实际加载比任何其他方法都好 - 本周仅通过包装代码解决了几个问题是零间隔计时器!
    • @mmacneill123 - 是的 - 你是对的,确实如此! (不过,我已经看到 Mobile Safari 的一些怪癖,即使 setTimeout 也不能​​保证存在 DOM 更改......奇怪的东西!)你能解决你的问题吗?
    • 是的,杰克,这一切都是用 jQuery 写的!从标记复制并粘贴生成的 ASP.NET 代码,设置 Autopost=False 以便 ASP.NET 不再发出它,然后手动附加事件。认为我在普通的 javascript 处理程序和 jQuery 之间感到困惑!
    【解决方案2】:

    这是因为 HTML 中的 onchange 在您的 jQuery 绑定事件运行之前运行首先。你不能阻止它运行,因为它已经运行了。您需要做的是 remove 在通过 jQuery 添加 HTML 绑定事件之前。

    $(document).ready(function(){
        var $select = jQuery('select'),  // Cache jQuery selector
            HTML_event = $select.prop('onchange'); // Backup original event
    
        $select.removeProp('onchange');  // Remove original event
    
        $select.change(function(e){
            alert("Hi");
    
            //HTML_event.call(this, e.originalEvent); // If you want to call the original event
        });
    });
    

    另一种解决方案是保存 timeoutID,然后对其调用clearTimeout

    <select onchange="window.selectTimeout = setTimeout(function(){}, 0)">
    </select>
    
    $(document).ready(function(){   
        jQuery('select').change(function(e){
            alert("Hi");
    
            clearTimeout(window.selectTimeout); // clears the timeout
        });
    });
    

    【讨论】:

    • 这里不信!警报确实按我的预期显示,返回然后页面重新发布!堆栈上还有其他示例是我所追求的行为,例如*.com/questions/18002368 我知道我可以通过删除事件并将其重新添加来解决这个问题,这就是我在其他地方所做的,但只是对为什么行为看起来如此不同感到困惑!
    • @mmacneill123:在您的示例中,当您更改值时,要触发的第一个事件是 HTML 中设置的 onchange。这在setTimeout. 中调用__doPostBack 函数。超时意味着浏览器将运行您的jQuery 绑定事件,然后稍后返回__doPostBack。因此,然后您的事件运行,alert 打开(暂停所有其他 JavaScript 执行)直到它关闭。你不能“阻止”onchange,因为它已经完成了。当警报关闭时,浏览器会返回并从超时运行__doPostBack
    • P.S. onchange 中有一些不好的做法。 1)不要在onchange中添加javascript:(它不会做你认为它做的事情),2)不要将字符串传递给setTimeout(它调用eval)。
    • P.P.S.我从未使用过 APP.NET,所以我不知道 __doPostBack 是如何工作或设置的,但我知道 JavaScript :-)
    【解决方案3】:

    我使用的实际解决方案是创建一个包含 ASP.NET 生成的回发的单个 jQuery 过程。通过从 ASP.NET 标记中删除 Autopost=True ,您可以精确控制正在发生的事情,并且仍然调用 ASP.NET 回调,但改用 jQuery 编写它。

    【讨论】: