Angular 1 实现多标签页效果
程序员文章站
2022-04-29 23:32:57
...
Angular 1 实现多标签页效果
背景:
我们的后台页面使用了 angular 1 + ui-router. 每点击一个页面时, 切换一个路由.
// 路由
app.config(function($stateProvider,$urlRouterProvider,$ocLazyLoadProvider) {
$stateProvider
.state('welcome',{
url: "/", // root route
templateUrl:"view/welcome.html"
})
.state('admin', {
url: '/:folder/:page',
templateUrl : function($stateParams) {
return "view/"+$stateParams.folder+"/"+$stateParams.page+".html";
},
//cache: false,
resolve:{
loadMyCtrl:function($ocLazyLoad,$stateParams){
return $ocLazyLoad.load("view/"+$stateParams.folder+"/"+$stateParams.page+"Ctrl.js");
}
}
})
$urlRouterProvider.otherwise("welcome");
});
实现的效果如下
需求
原来的页面的实现是每点击一菜单,切换一个页面, 这种方式在使用上不甚方便。现要求用户界面必须为标签页方式实现, 且切换标签时页面内容无刷新,效果如下:
实现方案
方案一:依旧使用路由(未能满足需求)
每点击一个菜单项时新增一个页签, 页签切换时, 还是使用的 路由功能, 加载新的页面需要重新从后台获取数据.考虑过在切换页面时, 在浏览器端缓存上一页面的数据, 返回上一页面,使用缓存对页面进行渲染。此方式 需要对已有的页面功能进行改造, 代价比较高。
查阅资料,angular 高级版本有“路由重用”的概念,但是在angular 1 版本无法实现。
最终:废弃路由,使用ng-include指令
点击菜单时,相当于在窗口中同时打开多个页面,关闭页面时,使用ng-if 将页面隐藏。关键点是uib-tabset (来自于ui-bootstrap-tpls )与ng-include指令的使用,同时废弃了路由的使用。
页面效果如下:
主页main.html中 关键代码
<uib-tabset active="$root.pages.active">
<uib-tab ng-repeat="page in pages" select="selectPage(page)" index="page.url" ng-if="!page.hide">
<uib-tab-heading>{{page.text}}
<button class="close tabClose" ng-click="closePage(page,$event)">×</button></uib-tab-heading>
<div class="view_body" ng-include="page.url" ></div>
</uib-tab>
</uib-tabset>
mainController.js中的关键代码
$rootScope.pages = [];//定义页面数组
function openPage(node){
node.selected = true;
$scope.curMenu = node;
var pathinfo = node.url.split('?');
var path =pathinfo[0];
$ocLazyLoad.load("/admin/view/" + path + "Ctrl.js").then(() => {
let pageUrl = "/admin/view/" + path + ".html";
let page = $rootScope.pages.find(n => n.url == pageUrl);
if (!page) {
$rootScope.pages.push({text: node.text,oriUrl:node.url, url: pageUrl})
}else{
page.hide = false;
}
setTimeout(() => {
$rootScope.pages.active = pageUrl;
$scope.$applyAsync();
})
})
}
$scope.closePage = function(page,$event){
let openedPages = $rootScope.pages.filter(n=>!n.hide);
let index = openedPages.indexOf(page);
if($rootScope.pages.active == page.url){
if(openedPages.length>1){
let toBeActivePage = index==0?openedPages[1]:openedPages[index-1];
$rootScope.pages.active = toBeActivePage.url;
toBeActivePage.hide = false;
}else{
$rootScope.pages.active = null;
}
}
page.hide = true;
$event.preventDefault();
}
实现 f5页面刷新时,自动打开上次打开页面
每次页面打开时,在当前url 加上 #开头的 页面后缀,比如http://localhost:3000/admin/main.html#/intelliDept/outwork。
然后在刷新时,根据 #后缀,跳转到指定页面。
//切换页面时,执行此方法
$scope.selectPage = function(page){
location.hash = page.oriUrl;
}
function openLastUrl(){
let hash = location.hash ;
if(hash && hash.indexOf("#/")==0){
let url = hash.substr(2);
let menu = menuData.find(n=>n.url == url)
if(menu){
openPage(menu);
}
}
}
app.loginPromise.then(function(){
openLastUrl();
})
上一篇: JDBC(1)----------基础和简单实现案例
下一篇: shell 环境变量