2015-11-10 5 views
4

В настоящее время я использую Backbone.Marionette для создания SPA и в одном из представлений пользователь может перемещаться с несохраненными изменениями. Я могу контролировать некоторые из этих событий, такие как кнопки и опции меню в представлении, которые отбирают пользователя, но некоторым другим потребуется манипулировать либо Backbone.Router, либо напрямую работать с событиями DOM.Запретить пользователю перемещаться с несохраненными изменениями

Я уже пробовал слушать beforeunload (не работает, поскольку приложение все еще загружено) и hashchange (не работает, так как вы не можете остановить браузер от навигации). Эти решения (1, 2, 3) не работают в этом случае, Javascript никогда не выгружается.

Изменение схемы Backbone.Router кажется лучшим вариантом, но из-за того, как он инициализирован, я не думаю, что можно представить эту функцию или, по крайней мере, я не могу найти способ сделать это. This solution, например, не работает, потому что hashchange не отменяется (вы не можете вызвать stopPropagation на нем), а this other solution не работает, потому что navigate не определен на объекте Backbone.Router.

Любые предложения?

ответ

0

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

Существует 4 основных способа выхода из вида;

  1. Нажмите на ссылку в представлении
  2. Нажмите на ссылку вне поля зрения
  3. Нажмите на обновления или внешней ссылке
  4. Нажмите на перемотки вперед/назад в браузере

1 Ссылка на приложение

Это самый простой случай. Когда вы нажимаете на свою собственную ссылку, вы должны проверить, загрязнен ли ваш взгляд. Например, у меня есть кнопка возврата в приложение, которая обрабатывается функцией historyBack. По мнению:

historyBack: function() { 
    if (this.isDirty) { 
     answer = confirm("There are unsaved changes.\n\nDo you wish to continue?") 

     if (answer) { 
      this.isDirty = false 
      window.history.back() 
     } 
    } 

    else { 
     window.history.back() 
    } 
} 

2. Ссылки вне вашего зрения

Этого типа взаимодействия может быть обработан путем расширения execute способа прототипа маршрутизатора, а не метод navigate, как предложено в других местах.

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

Код должен выглядеть примерно так:

_.extend(Backbone.Router.prototype, { 

    execute: function (callback, args, name) { 
     if (Backbone.Router.isDirty) { 
      answer = confirm "There are unsaved changes.\n\nDo you wish to continue?"; 

      if (!answer) { 
       return false; 
      } 
     } 

     Backbone.Router.isDirty = false 
     if (callback) callback.apply(this, args) 
    } 
} 

3.Обновление или внешняя ссылка

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

onShow: function() { 
    $(window).bind("beforeunload", function (e) { 
     if (this.isDirty) { 
      return "There are unsaved changes."; 
     } 
    } 
} 

onDestroy: function() { 
    $(window).unbind("beforeunload"); 
} 

4. Назад/Вперед в браузере

Это самый сложный случай и тот, который я еще не понял. При ударе назад/вперед пользователь может перейти из приложения или в приложение, оба случая покрываются кодом 1 и 3, но есть проблема, которую я не могу понять, и я создам для нее еще один вопрос ,

При ударе назад/вперед браузер меняет адресную строку перед вызовом маршрутизатора, поэтому вы оказываетесь в несогласованном состоянии: адресная строка показывает другой маршрут к состоянию приложения. Это большая проблема, если пользователь снова нажимает кнопку «Назад» после сохранения или отмены изменений, она будет отправлена ​​на еще один маршрут, а не на предыдущий.

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

Смежные вопросы