jQuery检测到对字段的程序化更改

时间:2010-11-17 00:10:02

标签: jquery

我有一个名为#myHiddenField的隐藏字段。

此字段的内容在各个地方以编程方式更改。

我想要一种检测变化的方法。除非我输入字段,否则更改事件不会触发,但这是不可能的。

是否有一种jQuery方法可以检测字段中的程序化内容变化?

5 个答案:

答案 0 :(得分:26)

您应该能够通过以下方式触发更改事件:

$('#myHiddenField').change();

OR

$('#myHiddenField').trigger('change');

当然,这需要负责更新字段的代码块,以便在完成其工作后进行其中一个调用。

答案 1 :(得分:6)

DOM无法检测到事件的程序化提升。我昨天碰到了这个。我不记得我在哪里阅读它,但解决方法是在jQuery元素上实际调用.trigger()jQuery Doc

答案 2 :(得分:1)

案例1: 您希望自己以编程方式更改值,并且只想在值更改时调度事件。

$('#myfield').text('New value');
//$('#myfield').val('New value');
$('#myfield').trigger('change');

案例2:

假设您要检测对您未编写的字段的编程更改。因此,您无法触发“更改”事件。

在这种情况下,使用'DOMSubtreeModified'来检测对父元素的后代元素的编程更改。

示例:

<div id="product-addons-total">
    <div id="total_price">200</div>
</div>

$(document).ready(function() {

    jQuery('#product-addons-total').on("DOMSubtreeModified",function(){
        console.log('content changed');
        //tamp_price_change_handler();
    });
});

现在,如果“total_price”的值以某种方式以编程方式更改,则会触发“DOMSubtreeModified”事件。    例如:

jQuery('#total_price').text('300');

案例2的注意事项: DOMSubtreeModified 可以创建无限循环并极大地降低性能。相反,鼓励使用 MutationObserver

MutationObserver示例:

// create an observer instance
var observer = new MutationObserver(function(mutations) {
  mutations.forEach(function(mutation) {
    console.log(mutation.type);        
  });    
});

// Let's configure the observer
var config = { childList: true, subtree:true, attributes: true, characterData: true,
    characterDataOldValue: true, attributeOldValue: true };
//Let's get a node.
var target = jQuery('#product-addons-total').get(0); 
// Let's pass the target and configuration to the observe function.
observer.observe(target, config); 

案例3:

以上方法可以检测DOM的变化。但是,如果要以编程方式更改输入字段的值,则不会触发这些事件。在这种情况下,唯一的方法是手动触发事件。 因此,首先更改输入字段的值,然后手动触发事件。

$('#inputfield').val(456465).trigger('change');

//Now the change event will fire.
$('#inputfield').on('change', function() {  
    console.log('input filed has been changed');
});

答案 3 :(得分:0)

在jQuery中使用.val()设置值不会触发更改事件,因此您必须使用.change()或.trigger(&#39;更改&#39;)来触发改变事件。您可以选择使用.change(function(){...})或.on(&#39;更改&#39;,function(){...}来检测字段的更改事件。

$('#myHiddenField').change(function() {
    alert('content changed to: ' + $('#myHiddenField').val());
});

$('#btnChange').click(function() {
    $('#myHiddenField').val("new content");
    $('#myHiddenField').change();
});

https://jsfiddle.net/qeg5of2a/1/

$('#myHiddenField').on('change', function() {
    alert('content changed to: ' + $('#myHiddenField').val());
});

$('#btnChange').click(function() {
    $('#myHiddenField').val("new content");
    $('#myHiddenField').trigger('change');
});

https://jsfiddle.net/qeg5of2a/2/

.change只是.on(&#39;更改&#39;,处理程序)和.trigger(&#39;更改&#39;)的快捷方式,所以要么很好

答案 4 :(得分:0)

您可以对JQ对象的方法(例如valhtml进行重写以实现此目的(或者可能覆盖“纯JS”对象的方法)。我个人无法让MutationObserver工作,我提出的这个解决方案可能更简单:

const jqInvoiceNo = $('#InvoiceNo');
const jqProto = Object.getPrototypeOf( jqInvoiceNo );
const valOverride = function( newVal ){
    console.log( '£ override val, invoice no: ' + newVal );
    // essential function 'call'... note usage
    // we assume that if newVal is undefined this means we are using the
    // parameterless JQ method signature version, which returns the value
    if( newVal === undefined ){
        return jqProto.val.call( this );
    }
    jqProto.val.call( this, newVal );

    // ... then do something else, having intercepted the value-setting mechanism
};
jqInvoiceNo.val = valOverride;

... // later, in your code:

jqInvoiceNo.val( '99' );

重要说明:此代码只写覆盖/覆盖此一个JQ对象的val方法。必须要注意的是,如果你去其他地方$( '#InvoiceNo' ),你实际上将创建一个全新的JQ对象,而没有被覆盖的val方法。换句话说,在这种情况下,您可以跟踪JQ对象。

你也可以用同样的方式覆盖任何“纯JS”对象的方法,特别是(对于这种情况)setAttribute

对于那些还不知道的人来说,JQ对象的第一个元素,即[0],是它所包含的“真正的”JS对象。

const invoiceNo = $('#InvoiceNo')[ 0 ];
const proto = Object.getPrototypeOf( invoiceNo );
const setAttributeOverride = function( attr, newVal ){
    console.log( '£ override setAttribute, invoice no: ' + newVal );
    // essential function 'call'... note usage:
    proto.setAttribute.call( this, attr, newVal );
    if( attr === 'value' ){
        // ... then do something else, having intercepted the value-setting mechanism
    }
};
// note that only this object 'invoiceNo' will be given the overridden method:
invoiceNo.setAttribute = setAttributeOverride;

.... // later, in your code:

$( '#InvoiceNo' )[ 0 ].setAttribute( 'value', '99' );

与上面给出的JQ示例不同,只有一个这样的“纯JS”对象......所以在代码中的任何地方运行$( '#InvoiceNo' )[ 0 ]总会给你相同的JS对象。当然,在“纯JS”中设置属性(或者更确切地说是“属性”)的常规方法是

 object.value = newValue;

...据我所知,哪个命令不能被“覆盖”。据推测,如果你比我更成功,可以用MutationObserver检测到这一点。

PS究竟如何在调用valhtml之类的JQ方法时设置其“真正的JS”对象的值,我不知道。如果你想要可以实际上覆盖这些方法来“自己动手”,利用“等效”JQ对象引用相同底层JS对象的事实,即自$( '#InvoiceNo' )[ 0 ]以来总是指同一个JS对象。但在这种情况下,您必须覆盖{strong>所有 JQ对象的valhtml,即修改原型本身:

const jqInvoiceNo = $('#InvoiceNo');
const jqProto = Object.getPrototypeOf( jqInvoiceNo );
jqProto.superValMethod = jqProto.val;
const valOverride = function( newVal ){
    if( newVal === undefined ){
        return jqProto.superValMethod.call( this );
    }
    jqProto.superValMethod.call( this, newVal );

    const ourPureJSObject = this[ 0 ];
    // do something with this ... it will always the right one!
};
jqProto.val = valOverride;