简体   繁体   中英

javascript property change event

I need to fire an event every time a property is updated/changed in order to keep dom elements in sync with the property values on the model (Im using john resig's simple inheritance http://ejohn.org/blog/simple-javascript-inheritance/ ). Is this possible to do in a cross-browser way? It seems to me that if I could wrap whatever function js uses to set properties and make it fire an event, that it could work, Im just not sure how to do that.

JavaScript doesn't use a function to set properties. They're just variables, and setting them doesn't require any elaborate wrappers.

You could use a function to set the property, though — the same sort of a getter/setter arrangement you might use in a language that supported private data in classes. In that way your function could easily run other functions that have been registered as callbacks. Using jQuery you can even handle those as events.

$(yourObject).bind('some-event-you-made-up', function() { 
    // This code will run whenever some-event-you-made-up is triggered on yourObject
});

// ... 

$(yourObject).trigger('some-event-you-made-up');

Maybe you already solved your problem with jQuery bind/trigger, but I wanted to tell that I'm building a Change Tracking and (in top of that) Entity Modeling Javascript Framework, named "tent" that solves the problem you exposed, without requiring any special syntax on object manipulation, its open source and hosted at:

https://github.com/benjamine/tent

It's documented with JSDoc and unit tested with js-test-driver.

you can use the change tracking module this way:

   var myobject = { name: 'john', age: 34 };

   // add a change handler that shows changes on alert dialogs
   tent.changes.bind(myobject, function(change) {
       alert('myobject property '+change.data.propertyName+' changed!');
   });

   myobject.name = 'charly'; // gets notified on an alert dialog

it works with Array changes too (adds, deletes). Further you can use "Entity" Contexts to keep a changesets of all detected changes (ADDED, DELETED, MODIFIED items) grouped on collections, cascade adds and deletes, keep reverse properties synced, track 1-to-1, 1-to-N and N-to-M relationships, etc.

Object defineProperty/defineProperties does the trick. Here goes a simple code. I have built some data binding frameworks based on that, and it can get really complex, but for exercising its like this:

var oScope = {
    $privateScope:{},
    notify:function(sPropertyPath){
        console.log(sPropertyPath,"changed");
    }
};
Object.defineProperties(oScope,{
    myPropertyA:{
        get:function(){
            return oScope.$privateScope.myPropertyA
        },
        set:function(oValue){
            oScope.$privateScope.myPropertyA = oValue;
            oScope.notify("myPropertyA");
        }
    }
});

oScope.myPropertyA = "Some Value";
//console will log: myPropertyA changed

You could try Javascript Property Events (jpe.js)

I encountered a similar issue, and ended up writing an overload function for Object.defineProperty that adds event handlers to the properties. It also provides type checking (js-base-types) and stores its value internally, preventing unwanted changes.

Sample of normal defineProperty:

Object.defineProperty(document, "property", {
    get:function(){return myProperty},
    set:function(value){myProperty = value},
})
var myProperty = false;

Sample of property with onchange event:

Object.defineProperty(document, "property", {
    default:false,
    get:function(){},
    set:function(value){},
    onchange:function(event){console.info(event)}
})

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM