It depends. If you add an event listener inside a 'ready' event listener for the dashboard, then every time the dashboard fires a 'ready' event, another instance of the event listener will be created. Sometimes this is ok, sometimes you don't want this at all. There is no one "best" way.
Usually, the only thing that causes a dashboard to fire a 'ready' event is when you call the draw method. When this happens, all existing dashboard elements are destroyed (I assume cleanly) by the API and redrawn. Any event handlers you had put in place on the charts or controls themselves (ie, chart or control objects, not ChartWrappers or ControlWrappers) are destroyed along with the elements, and thus would need to be recreated.
If there is anything you don't want to instantiate a second time, you can destroy the 'ready' event listener:
var readyListener = google.visualization.events.addListener(dash, 'ready', function () {
// do some stuff
// then destroy this event listener
google.visualization.events.removeListener(readyListener);
});
You can create multiple 'ready' event listeners for the dashboard, to separate out things you only want to instantiate once and things that need to be reinstantiated when the dashboard is redrawn.