監聽瀏覽器返回按鈕(popstate)

1.在模態框中控制返回的按鈕,點擊返回應該關閉模態框angularjs

// 設置審批頁面的歷史記錄,用於打開模態框點擊返回時關閉模態框
function setHistory() {
  modalInstance.dismiss("cancel");
  window.removeEventListener("popstate", setHistory);
}

//模態窗口打開以後執行的函數
modalInstance.opened.then(function() {
  // 打開模態框須要關閉上一個返回按鈕監聽事件
  if (typeof(_goBack) != "undefined") {
	  window.removeEventListener("popstate", _goBack);
  }			  
  history.pushState(null, null, document.URL);
  window.addEventListener("popstate",setHistory, false);
});

//點擊肯定回調函數
modalInstance.result.then(function (retValue) {
  window.removeEventListener("popstate", setHistory);
    if (angular.isFunction(callbackFunc)) {
  	  callbackFunc();
    }
}, function (reason) {//點擊取消回調函數
  window.removeEventListener("popstate", setHistory);
});

2.在基本信息頁面中不斷的切換tab,點擊返回按鈕,返回到列表頁web

function pushHistory() {
   history.pushState(null, null, document.URL);
}
function _goBack() {
    pushHistory();
    window.location.href = document.referrer;
}

// 此部分代碼在angularjs的controller中編寫
// 延遲執行,避免頁面一打開就開始監聽
setTimeout(function() {
   pushHistory();
   window.addEventListener("popstate", _goBack, false);
},500);
  
// 頁面銷燬事件
$scope.$on('$destroy', function() {
	window.removeEventListener("popstate", _goBack);
});

總結: 1).在關閉頁面以後須要銷燬返回按鈕的監聽事件。 2).若是是打開模態框,在模態框打開的時候銷燬上一個頁面的監聽事件。 3).每個頁面都要知道上一個頁面的URL,且每個頁面都須要調用監聽函數。app

/**
 * 關於上面第三點的好的解決思路(共用$scope):
 * 在第一個頁面定義一個變量:$scope.canBack = true;
 * 打開彈窗時:$scope.canBack = false;
 * 在關閉彈窗或點返回按鈕時,會調用第一個頁面的監聽的返回按鈕的函數
 * 若是$scope.canBack = true執行函數裏面的內容,不然賦值$scope.canBack = true
 */
 $scope._goBack = function() {
   // 彈窗選擇以後會觸發
   if ($scope._canBack) {
	  // ...
	  $scope.$apply();
   }
   $scope._canBack = true;
 }
/**
 * 最好不要使用document.referrer,由於你從基本信息頁面切到列表頁的時候,
 * document.referrer記錄的是基本信息頁面的URL。
 * 因此應該放須要跳轉的具體頁面的URL,這就須要本身手動構建好URL。
 */
function _goBack() {
  pushHistory();
  window.location.href = document.referrer;
}

補充:
有一種case是:在模態框中在彈一個模態框,在第二個模態框中點擊返回按鈕時,兩個模態框都關閉了。正常的狀況下,應該是隻關閉第二個模態框。這涉及到了window.addEventListener的冒泡事件,試了一下下面這種狀況行不通。函數

function setHistory(e) {
  e = e || window.event;
  e.preventDefault();
  e.stopPropagation();
  modalInstance.dismiss("cancel");
  window.removeEventListener("popstate", setHistory);
}

解決方案是:定義一個全局的變量,標記當前在哪一個模態框。打開第二個模態框的時候修改變量,關閉第二個模態框的時候重置變量。在第一個模態框判判定義的變量的值。code

var propagationFlag = 0;

// 第一個模態框
function setHistory() {
  if (propagationFlag === 0) {
     modalInstance.dismiss("cancel");
     window.removeEventListener("popstate", setHistory);
  }
}

// 第二個模態框
function setHistory() {
    propagationFlag = 0;
    modalInstance.dismiss("cancel");
    window.removeEventListener("popstate", setHistory);
}

// 打開第二個模態框時
function openTwoModal() {
    propagationFlag = 1;
}

// 關閉第二個模態框時
function closeTwoModal() {
    propagationFlag = 0;
}

如何共用$scope?其實也就封裝成dialog成一個module就好了。大概的思路就這樣,擼直就能夠的了。事件

(function() {
    'use strict';  
    var dialogModule = angular.module('app.dialog', []).factory('Dialog', AngularDialog);
	function AngularDialog($modal, $rootScope, $http, $timeout) {
		return function($scope) {
			var dialog = {
				showDialog: function(args1, okCallbackFunc, cancelCallbackFunc, isAutoBackOnePage){
					  var resolve = {
						  args1: function () {
							return args1;
						  }
					  };	  
					  var modalInstance = $modal.open({
						  templateUrl: $rootScope.webContext + args1.templateUrl,
						  controller: args1.ctrlName,
						  resolve: resolve,
				          size : 'lg',
				      });
					  
					  function setHistory() {
						  dialogPropagationFlag.approvalStages = 0;
						  modalInstance.dismiss("cancel");
						  window.removeEventListener("popstate", setHistory, false);
					  }
					  
					  //模態窗口打開以後執行的函數
					  modalInstance.opened.then(function() {
						  // 用於上一個頁面也有監聽按鈕的狀況,_canBack爲true的時候才觸發第一個頁面的返回按鈕事件
						  $scope._canBack = false;
						  history.pushState(null, null, document.URL);
						  window.addEventListener("popstate", setHistory, false);					 
					  });
					  
					  //點擊肯定回調函數
					  modalInstance.result.then(function (retValue) {
						  dialogPropagationFlag.approvalStages = 0;
						  window.removeEventListener("popstate", setHistory, false);	      				  	      				  
						  if (okCallbackFunc) {
							  if (isEmptyString(isAutoBackOnePage) || isAutoBackOnePage) {
								  window.history.go(-1); // 歷史記錄回退一層
							  }						  
							  okCallbackFunc(retValue);
						  }						  
					  }, function (reason) {//點擊取消回調函數
						  dialogPropagationFlag.approvalStages = 0;
						  window.removeEventListener("popstate", setHistory, false);
						  if (cancelCallbackFunc) {
							  cancelCallbackFunc(reason);
						  }
					  });
				}
			}
			return dialog;
		}
	}
})();
相關文章
相關標籤/搜索