DurandalJS — обеспечение полного цикла активации в корне страницы (иначе: деактивация огня в app.setRoot())

[Изменить] Также есть ветка Google Groups здесь. Я постараюсь держать оба в курсе, когда узнаю больше.

Согласно документации Durandal, модель корневого представления страницы реализует только ограниченные функции активатора. В частности, в нем говорится, что:

....

4) Когда вы вызываете app.setRoot, в вашем корневом модуле используется (ограниченный) активатор.

Примечание. Случай 4 немного отличается, так как он применяет только обратные вызовы canActivate и активировать; а не жизненный цикл деактивации. Для этого вы должны самостоятельно использовать полный активатор (случаи 1-3).

Это означает, что в отличие от всех ViewModels с вложенными страницами, у корневых нет возможности избавляться от своих ненужных объектов и очищаться.

Каков дружественный способ запустить как canDeactivate, так и деактивировать эти объекты, когда я вызываю app.setRoot()? Возможно, я мог бы сделать это вручную, но мне понадобится ссылка на корневую ViewModel, которая не обязательно входит в область действия.

Я думал о создании своего рода системы pub/sub, хотя я устал от этого, потому что это может вызвать БОЛЬШЕ проблем с памятью и сложностью очистки, чем уменьшить ее.

Я рассматривал возможность разветвления проекта, хотя это сопряжено с большими накладными расходами, поскольку с этого момента мне придется поддерживать свою разветвленную структуру.

[РЕДАКТИРОВАТЬ]

Пример:

Допустим, я должен был запустить свое приложение и установить оболочку в «основную» оболочку.

  app.start().then(function () {
      app.setRoot('views/shells/main');
  })

Через некоторое время я хочу переключиться на новую оболочку. Возможно другой макет, полноэкранный режим или другой скин.

 app.setRoot('views/shells/accounts');

Это заставит «учетные записи» оболочки проверять и/или запускать активацию и канактивацию, но НЕ будет проверять «основную» оболочку на наличие canDeactivate и deactivate. У меня есть логика очистки, которую я хочу запустить, когда они исчезнут. Как я могу это сделать?

[РЕДАКТИРОВАТЬ]

Часть кода durandal, которая обрабатывает это, является локальной функцией, находящейся в модуле 'durandal/app' setRoot() finishComposition(). Выглядит это так

  function finishComposition() {
            if(settings.model) {
                if (settings.model.canActivate) {
                    try {
                        var result = settings.model.canActivate();
                        if (result && result.then) {
                            result.then(function (actualResult) {
                                if (actualResult) {
                                    composition.compose(hostElement, settings);
                                }
                            }).fail(function (err) {
                                system.error(err);
                            });
                        } else if (result) {
                            composition.compose(hostElement, settings);
                        }
                    } catch (er) {
                        system.error(er);
                    }
                } else {
                    composition.compose(hostElement, settings);
                }
            } else {
                composition.compose(hostElement, settings);
            }
        }

Возможно, есть способ исправить это? Я хотел бы избежать редактирования ядра Дюрандаля, если это возможно.


person Oliver Kane    schedule 11.06.2014    source источник


Ответы (1)


Вам действительно не нужно реализовывать несколько оболочек. Мы тоже смотрели на это в начале. Вы можете иметь одну оболочку, а затем сразу же динамически создавать внутреннюю оболочку внутри нее. Внутренние оболочки могут быть заменены динамической композицией, которая по-прежнему сохранит вашу высокоуровневую маршрутизацию. Другими словами, нет необходимости, чтобы каждое представление становилось дочерним маршрутом.

Другими словами, следующее будет располагаться на два уровня ниже, а не на один:

data-bind="router: { model: router.activeItem, cacheViews:false, compositionComplete: router.compositionComplete, attached: router.attached }">

Это будет перемещено во внутреннюю оболочку:

<div data-bind="compose: {model: currentShell()}"></div>

где currentShell() — это наблюдаемый объект, содержащий текущую оболочку (внутри модели представления вашей «супероболочки»).

person Community    schedule 16.06.2014
comment
Мне нравится этот ответ, и у меня возникает соблазн сразу же поставить ему зеленую галочку, но я хочу сначала посмотреть, смогу ли я заставить его работать. Я вернусь в офис в четверг днем. Хотя это выглядит действительно многообещающе. - person Oliver Kane; 17.06.2014
comment
@OliverKane О.К. Рад слышать! - person ; 20.06.2014