學習《AngularJS深度剖析與實踐》總結
- 在我們平時的開發中,需要對某些數據進行以樹的形式進行展現,比如:權限角色、菜單、嵌套評論等。這個時候我們需要使用angular進行對數據抽象,構造我們自己的組件樹:
- 例子:我們就拿主題樹作為一個例子,然后一步一步去優雅的實現它:
- 首先我們準備好angular的庫文件,建立好相應的目錄及文件,按照angular遵循的風格:約定優于配置。首先我們創建一個用于展示的目錄,theme-tree
mkdir theme-tree && cd $_
2.創建需要展示的html頁面文件:
touch index.html
3.創建存放項目js文件的目錄:
mkdir js
4.創建存放angular項目的controller目錄、service目錄和filter目錄:
mkdir controller && mkdir service && mkdir filter
5.創建angular項目的入口文件,app.js
cd js && touch app.js
6.目前先不考慮UI效果部分,主要以實現功能為主,我們使用bower來安裝和管理相應的js第三方庫文件,如果沒有安裝bower工具,可以借助npm進行安裝-npm install -g bower ,在我們創建的theme-tree目錄下,鍵入如下命令安裝angular庫的依賴:
bower install angular --save
以上命令實行完畢后我們的目錄結構如下:
7.接下來我們開始編輯js/app.js入口文件:
angular.module('myApp', []);
8.接下來我們開始編寫控制器文件js/controller/index.client.controller.js:
angular.module('myApp').controller("ThreedTreeCtrl",function ThreedTreeCtrl(tree) {
var vm = this;
vm.items = [{
id: 1,
title: "Java",
poster: "Messi",
dateCreated: "2012-02-19T00:00:00",
items: [{
id: 11,
title: 'Spring',
poster: 'John',
dateCreated: "2012-02-19T00:00:00",
items: [
{
id: 111,
title: 'AOP',
poster: 'Mike',
dateCreated: "2016-02-19T00:00:00",
items: [
{
id: 1111,
title: 'IOC',
poster: 'Jack']
}
]
}, {
id: 2,
title: "SpringBoot",
poster: "Lucy",
dateCreated: "2011-02-19T00:00:00"
}
]
}, {
id: 2,
title: "JavaScript",
poster: "Jack",
dateCreated: "2012-02-19T00:00:00",
}
];
});
以上內容很簡單,構建了一個ThreedTreeCtrl控制器,里面嵌套了一些隨意的數據,主要是為了模擬父子關系;
9.接下來我們編輯js/service/index.client.service.js文件,用于對數據進行附加相應的行為。思考一下,當我們有了這樣一組數據后,我們要為它添加什么方法和屬性,首先應該添加父節點是否折疊,此屬性主要是為了在界面顯示的時候展開或折疊子節點數據。當展開的時候我們使用“-”表示,折疊的時候我們使用"+"表示,當折疊時單擊節點應該展開子節點,當展開的時候,單擊子節點應該折疊父節點;將新增的屬性和方法為了減小和原始數據沖突,并且這些數據通過$http或者$resource提交給服務器,它們所調用的angular.toJso()函數會忽略所有以$開頭的屬性,這樣我們擴展的屬性就不會被提交到服務端了。還有一個方便的是,當我們看到數據上有"$"開頭的屬性就是擴展的屬性。接下來我們實現它:
angular.module('myApp').service('tree',function Tree(){
var self = this;
//為每一項節點添加屬性和方法
var enhanceItem = function(item,childrenName){
item.$hasChildren = function(){
var subItems = this[childrenName];
return angular.isArray(subItems) && subItems.length;
};
item.$foldToggle = function(){
this.$folded = !this.$folded;
};
item.$isFolded = function(){
return this.$folded;
};
};
//對傳進來的數據進行強化
this.enhance = function(items,childrenName){
if(angular.isUndefined(childrenName)){
childrenName = "items";
}
angular.forEach(items,function(item){
enhanceItem(item,childrenName);
//如果有子節點則遞歸處理
self.enhance(item[childrenName],childrenName);
});
console.log(items);
return items;
};
});
10.這樣我們完成了對數據進行強化,此時我們如果直接在controller調用service的enhance 方法,將服務端返回的json數據進行加強,為他們添加的相應的屬性和方法,然后在頁面進行展示調用就可以了,但是這樣感覺比較臟,不干凈,我們不在contrller直接調用service里面的enhance 方法,我們可以創建一個過濾器來對數據進行添加過濾的功能,接下來我們開始編輯filter/index.client.filter.js:
angular.module('myApp').filter('tree',function(tree){
return function(items,childrenName){
tree.enhance(items,childrenName);
return items;
};
});
11.接下來編寫html文件,開始對主題樹進行展現并且引入相關文件:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
</head>
<body>
<div ng-app="myApp" ng-controller="ThreedTreeCtrl as vm">
<ul ng-if="vm.items">
<li ng-repeat="item1 in vm.items | tree">
<div ng-click="item1.$foldToggle()">
<span ng-if="item1.$hasChildren()">
<span ng-if="!item1.$isFolded()">-</span>
<span ng-if="item1.$isFolded()">+</span>
</span>
{{ item1.title }}
</div>
<ul ng-if="item1.$hasChildren() && !item1.$isFolded()">
<li ng-repeat="item2 in item1.items">
<div ng-click="item2.$foldToggle()">
<span ng-if="item2.$hasChildren()">
<span ng-if="!item2.$isFolded()">-</span>
<span ng-if="item2.$isFolded()">+</span>
</span>
{{ item2.title }}
</div>
<ul ng-if="item2.$hasChildren() && !item2.$isFolded()">
<li ng-repeat="item3 in item2.items">
{{ item3.title }}
</li>
</ul>
</li>
</ul>
</li>
</ul>
</div>
<script src="bower_components/angular/angular.js"></script>
<script src="js/app.js"></script>
<script src="js/controller/index.client.controller.js"></script>
<script src="js/service/index.client.service.js"></script>
<script src="js/filters/index.client.filter.js"></script>
</body>
</html>
此時我們便完成了對主題樹功能的實現,在index.html文件中,我們只展示了兩層嵌套關系以作為示例,根據自己的業務場景進行擴展。
以上實現還不夠優雅,等待以后需要將主題遞歸樹封裝為指令,最后附上github地址:
https://github.com/strongant/angularjs
源碼位于此倉庫下的angular-tree目錄,歡迎提出issue。