监听浏览器返回按钮(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;
		}
	}
})();
相关文章
相关标签/搜索