dojo/on
and dojo/aspect
are two APIs that appear to do similar jobs but actually serve two different purposes.dojo/on
is used to setup event listeners for DOM nodes and event-emitting objects.dojo/aspect
provides Aspect Oriented Programming facilities so functionality can be run before, after, or around a method call and can even manipulate the input to the original method or the original method’s output.
dojo/on
dojo/on
is the general purpose event module and can be used to listen for events on DOM nodes and event-emitting objects. The most basic use is to set up an event listener on an element directly or to use event delegation.
require([
'dojo/on',
'dojo/query'
], function(on) {
varactionButton = document.getElementById('actionButton');
// add event listener directly to a DOM Node
on(actionButton,'click', function() {
console.log('button clicked');
});
// use event delegation to listen for events
on(document,'.button:click', function () {
console.log('button clicked');
});
});
|
dojo/on
can also be used to set up listeners for events emitted from objects that inherit fromdojo/Evented
. These objects gain an
emit
method, which can be used to trigger a custom event.
|
require([
'dojo/_base/declare',
'dojo/Evented',
'dojo/on'
], function(declare, Evented, on) {
varMyClass = declare(Evented, {
run:function () {
this.emit('custom-event', { name:'world' });
}
});
varc = new MyClass();
on(c,'custom-event', function (data) {
console.log('hello, '+ data.name);
});
c.run();
});
|
dojo/aspect
On the other hand, dojo/aspect
can be used in a number of ways to run code before, after, or around a method call. For example, if we have arand
object that has a method
getNumber
which returns a random number in a given range, we can useaspect.after
to call a new method after the original method is executed and change the return value to be a little less random:
var div = document.querySelector('#result'),
after = document.querySelector('#after');
require([
'dojo/aspect'
], function(aspect) {
varrand = {
getNumber:function (min, max) {
returnMath.floor(Math.random() * (max - min + 1)) + min;
}
};
aspect.after(rand,'getNumber', function (value) {
console.log('actual result '+ value);
return4;
});
console.log('returned result '+ rand.getNumber(3, 10));
});
|
|
Similarly, we could use aspect.before
to execute code before
getNumber
is called and return an array, changing the arguments that are passed to the original function:
require([
'dojo/aspect'
], function(aspect) {
varrand = {
getNumber:function (min, max) {
returnMath.floor(Math.random() * (max - min + 1)) + min;
}
};
aspect.before(rand,'getNumber', function (min, max) {
console.log('original arguments: '+ min + ', ' + max);
return[6, 16];
});
console.log('returned result: '+ rand.getNumber(20, 30));
});
|
|
Finally, aspect.around
can be used to return a function to replace the original method. This new method can then conditionally call the original method if necessary:
require([
'dojo/aspect'
], function(aspect) {
varrand = {
getNumber:function (min, max) {
console.log('original method called');
returnMath.floor(Math.random() * (max - min + 1)) + min;
}
};
aspect.around(rand,'getNumber', function (origMethod) {
returnfunction (min, max) {
if(min === max) {
console.log('not calling original method');
returnmin;
}
// only call the original method if min !== max
returnorigMethod(min, max);
};
});
console.log('returned result: '+ rand.getNumber(20, 20));
});
|
|
As you can see, dojo/on
is a useful utility for listening for events from the DOM or event-emitting objects, whiledojo/aspect
is useful for injecting code before, after, or around the original method call.