AngularJS+Bootstrap3多級導航選單
AngularJS體驗式程式設計系列文章,將介紹如何用angularjs構建一個強大的web前端系統。angularjs是由Google團隊開發的一款非常優秀web前端框架。在當前如此多的web框架下,angularjs能脫穎而出,從架構設計上就高人一等,雙向資料繫結,依賴注入,指令,MVC,模板。Angular.js創新地把後臺技術融入前端開發,掃去jQuery一度的光芒。用angularjs就像寫後臺程式碼,更規範,更結構化,更可控。
關於作者
- 張丹(Conan), 程式設計師Java,R,PHP,Javascript
- weibo:@Conan_Z
-
email: [email protected]
前言
在上一篇文章中Angular結合Bootstrap3的導航選單,我們看到直接用Bootstrap3的預設導航菜單隻支援到二級的選單,如果想做成多級導航選單,那又要自己動手了。
本文將介紹如何實現多限級導航選單。
目錄
- 靜態多級選單實現
- 動態多級選單實現
1. 靜態多級選單實現
要實現多級選單,我們要分兩步走,第一步就是把靜態選單的功能實現,通過純靜態的HTML程式碼完成。第二步,通過Angluarjs進行動態實現,最後把資料和程式分離,通過Ajax載入多級選單資料。
我們先從靜態多級選單開始動手,一個六級導航選單是什麼樣子呢?
如上圖所示,我們定義一些功能需求。
- 1級選單是導航條上的文字。
- 當1級選單導航事件被觸發,顯示2級選單導航,在1級選單的正下方顯示。
- 當2級選單導航事件被觸發,顯示3級選單導航,在2級選單的右方顯示。
- 當3級選單導航事件被觸發,顯示4級選單導航,在3級選單的右方顯示。
- 以此類推,不考慮下級選單顯示出界問題。
繼續上文中的專案環境,增加一個新HTML檔案: page3.html
~ vi D:\workspace\javascript\angular-navbar\page3.html <!DOCTYPE html> <html lang="zh-cn"> <head> <meta charset="utf-8"> <title>多級導航選單</title> <meta name="description" content="多級導航選單"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="fragment" content="!" /> <link rel="stylesheet" href="/bower_components/bootstrap/dist/css/bootstrap.min.css"> <link rel="stylesheet" href="/css/main.css"> </head> <body ng-app="page2"> <div class="container"> <div class="row" ng-controller="NavbarCtrl"> <nav class="navbar navbar-default" role="navigation"> <div class="navbar-header"> <a class="navbar-brand" href="#">多級選單導航</a> </div> <div class="collapse navbar-collapse navbar-ex1-collapse"> <ul class="nav navbar-nav"> <li class="active"><a href="#">Link</a></li> <li><a href="#">Link</a></li> <li class="dropdown"> <a href="#" class="dropdown-toggle" data-toggle="dropdown">Multi Level <b class="caret"></b></a> <ul class="dropdown-menu menu-top"> <li><a href="#">Level 1</a></li> <li class="dropdown-submenu"> <a tabindex="-1" href="#">More options</a> <ul class="dropdown-menu"> <li><a tabindex="-1" href="#">Level 2</a> </li> <li class="dropdown-submenu"> <a href="#">More..</a> <ul class="dropdown-menu"> <li><a href="#">Level 3</a> </li> <li><a href="#">Level 3</a> </li> <li class="dropdown-submenu"> <a href="#">More..</a> <ul class="dropdown-menu"> <li><a href="#">Level 4</a> </li> <li><a href="#">Level 4</a> </li> <li class="dropdown-submenu"> <a href="#">More..</a> <ul class="dropdown-menu"> <li><a href="#">Level 5</a> </li> <li><a href="#">Level 5</a> </li> </ul> </li> </ul> </li> </ul> </li> <li><a href="#">Level 2</a> </li> <li><a href="#">Level 2</a> </li> </ul> </li> <li><a href="#">Level 1</a></li> </ul> </li> </ul> </div> </nav> </div> </div> <script src="/bower_components/jquery/dist/jquery.min.js"></script> <script src="/bower_components/angular/angular.min.js"></script> <script src="/bower_components/bootstrap/dist/js/bootstrap.min.js"></script> <script src="/bower_components/angular-route/angular-route.min.js"></script> <script src="/bower_components/angular-bootstrap/ui-bootstrap-tpls.min.js"></script> <script src="/js/app.js"></script> </body> </html>
新建一個css檔案:main.css
~ vi D:\workspace\javascript\angular-navbar\css\main.css
.dropdown:hover .menu-top {
display: block;
}
.dropdown-submenu{
position:relative;
}
.dropdown-submenu > .dropdown-menu{
top:0;
left:100%;
margin-top:-6px;
margin-left:-1px;
-webkit-border-radius:0 6px 6px 6px;
-moz-border-radius:0 6px 6px 6px;
border-radius:0 6px 6px 6px;
}
.dropdown-submenu:hover > .dropdown-menu{
display:block;
}
.dropdown-submenu > a:after{
display:block;
content:" ";
float:right;
width:0;
height:0;
border-color:transparent;
border-style:solid;
border-width:5px 0 5px 5px;
border-left-color:#cccccc;
margin-top:5px;
margin-right:-10px;
}
.dropdown-submenu:hover > a:after{
border-left-color:#ffffff;
}
.dropdown-submenu .pull-left{
float:none;
}
.dropdown-submenu.pull-left > .dropdown-menu{
left:-100%;
margin-left:10px;
-webkit-border-radius:6px 0 6px 6px;
-moz-border-radius:6px 0 6px 6px;
border-radius:6px 0 6px 6px;
}
通過HTML和CSS就實現了多級選單的靜態展示效果,如果導航選單不是經常變化,那麼用靜態的方式,把程式碼寫死就可以了。但有一些場景,選單是需要動態生成,比如通過許可權控制訪問連結,每個使用者的許可權不一樣,那麼能看到的選單選項也就不一樣,這個時候就需要做成動態的,用程式去控制選單的載入和展示。
2. 動態多級選單實現
有了靜態多級導航選單的HTML程式碼結構,改寫成動態的,其實也不太複雜。
我們需要做2件事:
- 把導航選單的資料結構化儲存,比如 存放到檔案 nav.json。
- 用Angularjs的API載入nav.json資料,進行展示。
我們先定義一下導航選單的資料格式,以JSON格式定義,每個選單項都有3個屬性欄位
- label: 導航選單項顯示的名字。
- link: 導航選單項的跳轉連結,可以不定義。
- children: 導航選單項的子選單,迴圈物件儲存。
{
"label": "levelA",
"link": "#",
"children": [
{
"label": "levelB",
"link": "#",
"children": []
}
]
}
下面我們用真實的資料定義導航選單,以我的金融系統為例。
新建JSON資料檔案:nav.json。
~ vi D:\workspace\javascript\angular-navbar\js\nav.json
[
{
"label": "債券",
"children": [
{
"label": "可轉債",
"children": [
{"label": "可轉債溢價率分析","link":"#"},
{"label": "可轉債NS定價","link":"#"},
{"label": "可轉債歸因分析","link":"#"},
{"label": "可轉債套利實時監控","link":"#"}
]
},
{
"label": "信用債",
"children": [
{"label": "交易所債券監控","link":"#"}
]
},
{
"label": "利率債","link":"#",
"children": []
},
{
"label": "國債期貨",
"children": [
{"label": "國債期貨表現分析","link":"#"},
{"label": "國債期貨實時套利監控","link":"#"},
{"label": "IRR歷史時間序列查詢","link":"#"},
{"label": "IRR實時監控","link":"#"}
]
}
]
},
{
"label": "股票",
"children": [
{
"label": "基本面分析",
"children": [
{"label": "上市公司基本面資料檢視","link":"#"}
]
},
{
"label": "量化選股策略",
"children": []
}
]
},
{
"label": "巨集觀",
"children": [
{
"label": "巨集觀資料",
"children": [
{"label": "巨集觀資料概覽","link":"#"}
]
},
{
"label": "巨集觀經濟預測",
"children": []
},
{
"label": "巨集觀經濟和大類資產表現",
"children": []
}
]
}
]
我們看到這個導航選單的資料,有3級,“債券–>可轉債–>可轉債歸因分析”,那麼接下我們就直接實現對三級選單的程式設計。建立HTML檔案page4.html。
~ vi D:\workspace\javascript\angular-navbar\page4.html
<!DOCTYPE html>
<html lang="zh-cn">
<head>
<meta charset="utf-8">
<title>多級動態導航選單</title>
<meta name="description" content="多級動態導航選單">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="fragment" content="!" />
<link rel="stylesheet" href="/bower_components/bootstrap/dist/css/bootstrap.min.css">
<link rel="stylesheet" href="/css/main.css">
</head>
<body ng-app="page4">
<div class="container">
<div class="row" ng-controller="NavbarCtrl">
<nav class="navbar navbar-default" role="navigation">
<div class="navbar-header">
<a class="navbar-brand" href="/">量化投資平臺</a>
</div>
<div class="collapse navbar-collapse navbar-ex1-collapse">
<ul class="nav navbar-nav">
<li ng-repeat="a1 in navbar" class="dropdown">
<a href="?{{ a1.label }}" class="dropdown-toggle" data-toggle="dropdown">{{ a1.label }} <b class="caret"></b></a>
<ul class="dropdown-menu menu-top">
<li ng-repeat="a2 in a1.children" class="dropdown-submenu">
<a tabindex="-1" href="?{{ a2.label }}">{{ a2.label }}</a>
<ul ng-show="a2.children.length>0" class="dropdown-menu">
<li ng-repeat="a3 in a2.children">
<a href="?{{ a3.label }}" ng-click="go(a3.link)">{{ a3.label }}</a>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</div>
</nav>
</div>
</div>
<script src="/bower_components/jquery/dist/jquery.min.js"></script>
<script src="/bower_components/angular/angular.min.js"></script>
<script src="/bower_components/bootstrap/dist/js/bootstrap.min.js"></script>
<script src="/bower_components/angular-route/angular-route.min.js"></script>
<script src="/bower_components/angular-bootstrap/ui-bootstrap-tpls.min.js"></script>
<script src="/js/app.js"></script>
</body>
</html>
在Angularjs的控制器檔案app.js檔案中,增加page4的定義。
var page4 = angular.module('page4', ['ui.bootstrap', 'ngRoute']);
page4.config(['$routeProvider', '$locationProvider', '$sceProvider', function ($routeProvider, $locationProvider, $sceProvider) {
$routeProvider
.when('/', {controller: 'DemoCtrl'})
.otherwise({redirectTo: '/'});
$locationProvider.html5Mode(true);
}]);
page4.controller('NavbarCtrl', function ($scope,$http,$location) {
$http.get("/js/nav.json").success(function(json){
$scope.navbar = json;
});
});
page4.controller('DemoCtrl', function () {
// nothing
});
檢視一下顯示效果,與上面的截圖類似。
文章到這裡就結束了,已經實現了我的功能需求。但這個話題還有很多可以優化的地方,比如實現無限級的導航選單,選單的展示樣式替換,展示區間的控制,滑鼠動作事件,封裝成Angularjs的外掛開源專案等。有興趣的同學,可以我的程式的基礎上繼續努力,做出優秀的開源專案來。
git clone https://github.com/bsspirit/angular-navbar.git
cd angular-navbar
bower install
anywhere