AppGyver Supersonic навигация между представлениями и создание дубликатов

Я использую AppGyver Steroids и Supersonic для создания приложения, и у меня возникают проблемы с навигацией между представлениями программно.

На основе документов вы перемещаетесь между представлениями следующим образом:

var view_obj = new supersonic.ui.View("main#index");
supersonic.ui.layers.push(view_obj);

Однако, когда я проверяю вещи с помощью Chrome DevTools, кажется, что создается второе дублированное представление, т. Е. Если я ухожу со страницы индекса, а затем возвращаюсь назад, у меня теперь есть две страницы индекса вместо того, что [я думаю] должно быть один. Это также не закрывает предыдущий вид, в котором я был.

Как я могу предотвратить это и просто перейти к существующему представлению вместо дублирования представлений? Как закрыть представление после выхода из него?

Спасибо.


person BannerMan    schedule 26.03.2015    source источник
comment
Несвязанный: спасибо за создание тегов appgyver и supersonic. :)   -  person Carlo Zottmann    schedule 27.03.2015


Ответы (3)


Проблема, с которой вы столкнулись, заключается в том, что вы создаете new supersonic.ui.View("main#index") каждый раз, когда перемещаетесь. Вдобавок ко всему, я думаю, вы хотите вернуться к тому же представлению, когда вы переходите обратно к представлению во второй раз, то есть вы хотите, чтобы представление оставалось в памяти, даже если оно было удалено из стека навигации с помощью pop() (скорее чем нажатие нового экземпляра этого представления). Для этого вам необходимо предварительно загрузить или "start()" представление, как описано в документах здесь.

Я реализовал свою собственную вспомогательную функцию, чтобы сделать это проще; вот мой код:

start = function(dest, isModal) {
  var viewId=dest,
      view=new supersonic.ui.View({
        location: dest,
        id: viewId
      });
  view.isStarted().then(function(started) {
    if (started) {
      if (isModal) {supersonic.ui.modal.show(view);}
      else {supersonic.ui.layers.push(view);}
    } else {
      // Start Spinner
      supersonic.ui.views.start(view).then(function() {
        if (isModal) {supersonic.ui.modal.show(view);}
        else {supersonic.ui.layers.push(view);}
        // Stop Spinner
      }, function(error) {
        // Stop Spinner
        A.error(error);
      });
    }
  });
};

Используйте его как start('module#view');. В качестве бонуса вы можете передать true в качестве второго аргумента, и вместо этого он будет передан как модальный.

Он проверяет, запустили ли вы уже представление, и если это так, оно просто помещает это представление обратно в стек. Если нет, он start()s (т.е. предварительно загружает) его, а затем отправляет. Это гарантирует, что представление останется в памяти (с любым измененным пользовательским вводом), даже когда вы pop() извлекаете его из стека.

Вы должны представить, что стек слоев на самом деле является стеком в смысле информатики. Вы можете добавлять и удалять представления только в верхней части стека. Следствием этого является то, что сложные переходы, такие как A > B > C > D > B, сложны/сложны для выполнения (в этом случае вам нужно последовательно pop() D и C, чтобы вернуться к B).

Представления будут закрыты, если вы pop() их, если вы не сделали start() их. Если вы это сделали, и вы pop() их, они остаются в памяти. Чтобы убить это представление, вы должны вызвать для него stop(), как описано в документах, на которые я ссылался выше.

person benadamstyles    schedule 27.03.2015
comment
Большое спасибо за это, братан, я попробую. Кроме того, я ожидаю, что такая платформа, как AppGyver, действительно проделает небольшую дополнительную работу по абстрагированию этих сложных взаимодействий, чтобы упростить работу разработчиков. - person BannerMan; 28.03.2015
comment
Да, я думаю, вы правы... Проблема, с которой, я думаю, они часто сталкиваются, заключается в том, что им нужно работать в рамках ограничений двух операционных систем (Android и iOS), оставаясь при этом такими же родными, как можно в обоих. Я думаю, это означает, что они ограничены стандартными, проверенными программными шаблонами, такими как стек слоев. Здесь есть все абстракции, вам просто нужно немного поработать, если вы хотите действительно настраиваемую реализацию. Учитывая, что мы не платим ни цента, я думаю, это достаточно справедливо! - person benadamstyles; 28.03.2015
comment
Я понимаю, что ты хочешь быть свободным, но то, что вода бесплатная, не означает, что ты будешь пить ее грязной. Я ценю всю работу, проделанную AppGyver над этим, но это должно быть проще. Я попробовал ваш код, но он не сработал. Он сделал то же самое. Я делаю что-то неправильно? У меня уже есть предварительно загруженные представления из моего structure.coffee, и я использую <super-navigate>, должен ли я отключить эту функцию и использовать вашу функцию с самого начала? - person BannerMan; 28.03.2015
comment
Хорошо, немного повозившись, я отключил все и использовал вашу функцию для предварительной загрузки представлений (вместо использования structure.coffee) и использовал контроллеры для включения перемещения от представления к представлению (вместо использования <super-navigate>, и это работает хорошо. Однако у меня есть форма, которая ссылки на функцию AJAX, и я хочу перенаправить обратно к предыдущему представлению при успешном обратном вызове. Я использовал вашу функцию start, но она не переходит обратно к представлению. Пытаюсь выяснить, почему это происходит. - person BannerMan; 28.03.2015
comment
Одна из ошибок, которые я получаю в console.log, это supersonic.logger.error: supersonic.ui.layers.push rejected: {} Unhandled rejection Error: The specified child already has a parent. You must call removeView() on the child's parent first. . Любая идея, что дает? Ваше здоровье. - person BannerMan; 28.03.2015
comment
Отлично, рад, что работает. Лично я считаю, что super-navigate — это слишком далеко за рамки одной абстракции, она требует такой упрощенной структуры приложения (насколько я понимаю), что я никогда ее не использовал. В любом случае, ваша ошибка: когда вы говорите «перейти назад», вы имеете в виду, что предыдущее представление уже находится в стеке навигации? Если да, пробовали ли вы supersonic.ui.layers.pop() (документы здесь< /а>)? Это стандартный правильный способ перехода назад. РЕДАКТИРОВАТЬ: только что видел ваш ответ! Рад, что вы разобрались :) - person benadamstyles; 28.03.2015
comment
Да, это было моей проблемой. Я не мог понять, как все работает, но я понимаю сейчас. Спасибо за руководство. - person BannerMan; 30.03.2015


Спасибо LeedsEbooks за помощь в решении этой задачи. Я смог найти решение. Вот код:

  var start = function(route_str, isModal) {

      var regex = /(.*?)#(.*)/g;
      var match_obj = regex.exec(route_str);

      var view_id_str = match_obj[2],
          view_location_str = route_str,
          view = new supersonic.ui.View({
              location: view_location_str,
              id: view_id_str
          });

      view.isStarted().then(function(started) {
          if (started)
          {
              if (isModal)
              {
                  supersonic.ui.modal.show(view);
              }
              else {
                  supersonic.ui.layers.push(view);
              }
          }
          else
          {
              // Start Spinner
              supersonic.ui.views.start(view).then(function() {
                  if (isModal)
                  {
                      supersonic.ui.modal.show(view);
                  }
                  else
                  {
                      supersonic.ui.layers.push(view);
                  }
                  // Stop Spinner
              }, function(error) {
                  // Stop Spinner
                  A.error(error);
              });
          }
      });
  };

Вы должны убедиться, что ваш маршрут имеет формат module#view, как определено в документации.

ВНИМАНИЕ

Кажется, возникла проблема с сверхзвуковым методом пользовательского интерфейса для запуска представлений. Если вы запустите следующий код:

supersonic.ui.views.start("myapp#first-view");
supersonic.ui.views.find("first-view").then( function(startedView) {
    console.log(startedView);
});

Вы заметите, что ваши представления id и location идентичны. Это кажется неправильным, так как id должно быть first-view, а location должно быть myapp#first-view.

Поэтому я решил не использовать методы AppGyver и вместо этого создал свой собственный метод предварительной загрузки, который я запускаю из контроллера, подключенного к моему домашнему представлению (это гарантирует, что все представления, которые я хочу предварительно загрузить, обрабатываются при загрузке приложения). Вот функция для этого:

  var preload = function(route_str)
  {
      var regex = /(.*?)#(.*)/g;
      var match_obj = regex.exec(route_str);
      var view = new supersonic.ui.View({
          location: route_str,
          id: match_obj[2]
      });
      view.start();
  };

Делая это, я уверен, что представление будет загружено с правильными location и id, и что, когда я буду использовать свою функцию start() позже, у меня не будет никаких проблем.

Убедитесь, что в вашем файле structure.coffee нет инструкций preload, чтобы не создавать повторяющиеся представления, с которыми у вас позже возникнут проблемы.

Наконец, у меня есть двухуровневое представление, которое представляет собой форму, которая отправляет данные через операцию AJAX. Я хотел, чтобы представление возвращалось к предыдущему представлению, когда операция AJAX была завершена. Использование моей предыдущей функции привело к отклонению push(). Было бы неплохо, если бы AppGyver Supersonic мог разумно определять, что переход к предыдущему представлению должен по умолчанию выполняться как операция layers.pop, но вы не всегда получаете то, что хотите. Во всяком случае, мне удалось решить эту проблему с помощью supersonic.ui.layers.pop(), который просто делает то, что сделала бы кнопка «Назад».

Теперь все работает как задумано.

person BannerMan    schedule 28.03.2015