Цитата:
Сообщение от Psycho Tiger
Конечно, сломать можно всё делая это специально - когда говорил "сломать" подразумевалось конечно же "ненароком менял вьюшку, а полетела всё остальное".
С этим появляется ещё 2 вопроса:
7) Насколько это хорошая практика - делать по 40 разных событий для 40 изменений - то есть, если изменился угол поворота чей нибудь - не обновлять положение в пространстве, а лишь повернуть (то есть разбиение например updatePositionEvent на updateXYPositionEvent и updateRotationEvent)
8) Если передается только интерфейс, тогда вся инфа об обновлении должна поступить вместе с Event`ом, а не через геттеры от модели о нужной информации?
|
вот эти вопросы самые сложные ( во всяком случае для меня)
в своеё реализации mvc я диспатчил события для изменения любого отдельного свойства
подписывался также.
вот пример из рабочего проекта ( as2)

Код AS1/AS2:
class ru.k0t0vich.mvc.models.Model extends EventDispatcher
{
public function Model(eventParentLink)
{
eventParent = eventParentLink;
}
/**
* Диспатчим событие об изменении структуры
* @param field - имя поля (должно присутьствовать в классе, иначе генерируется ошибка времени выполнения)
*/
public function update(field:String):Void
{
if (field == undefined) field = "";
var event: ModelEvent= new ModelEvent(ModelEvent.CHANGE+field);
// Проверка на доступность свойства
if (field != "")
{
try
{
event.field = this[field];
}
catch (e:Error)
{
trace (e);
}
dispatchEvent(event);
}
else
{
event.field = this;
dispatchEvent(event);
}
}
}
подписка во вью:

Код AS1/AS2:
public function addChangeModelFieldListener(field:String,listener:Function,scope:Object):Void
{
_model.addEventListener(ModelEvent.CHANGE + field, listener,scope);
// регистрируем для отписки от ВСЕХ событий модели
_modelFieldEventListenersArray.push( { event:ModelEvent.CHANGE + field, listener:listener,scope:scope } );
}
пример подписки:

Код AS1/AS2:
/**
* Инициализацие хэндлеров изменения модели
*/
private function initModelListeners()
{
addChangeModelFieldListener(SlotModelField.LINES, showLinesByModel, this);
addChangeModelFieldListener(SlotModelField.FREESPINS, updateFreespinsCounter, this);
addChangeModelFieldListener(SlotModelField.WIN, updateFreespinsCounter, this);
}
косяков в такой реализации много ( нет строгой типизации итп) но многое лечится вводом класса констант SlotModelField. доступ к геттерам модели у меня кстати тоже так сделан,

Код AS1/AS2:
private function updateFreespinsCounter(e:ModelEvent):Void
{
freespinsCounterWindow.freespins = model[SlotModelField.FREESPINS];
freespinsCounterWindow.cash = model[SlotModelField.WIN];
}
хотя можно сделать в IModel геттеры этих свойств - я не сделал т.к. при добавлении публичных обновляемых свойств в модели пришлось бы редактировать уже 3 класса ( Model, ModelField и IModel) а не 2 (Model, ModelField)
модель обновляется таким образом:

Код AS1/AS2:
public function get totalBet():Number { return _totalBet; }
public function set totalBet(value:Number):Void
{
_totalBet = value;
update(SlotModelField.TOTAL_BET);
}
В общем практика показала относительное удобство такого подхода..
хотя могло бы быть и лучше..
PS: основная "неправильность" моего подхода была в методе update который создаёт эвент с динамическим типом field. Практика показала, что на самом деле это поле практически не используется при слушании событий, т.к. у вида есть ссылка на нужный геттер и он может его просмотреть самостоятельно, а не в качестве свойства события..
так-что можно смело переписать метод update так:

Код AS3:
public function update(field:String):Void
{
if (field == undefined) field = "";
var event: ModelEvent= new ModelEvent(ModelEvent.CHANGE+field);
dispatchEvent(event);
}