1、如何使用yeoman快速的构建一个Angularjs环境
1.1、安装node/npm
sudo apt-get install nodejs
*注意:
1 有些时候安装nodejs后在/usr/bin/只有一个nodejs可执行文件,但是很多包包括node的脚本使用的是node,所以需要手动的建立一个node
sudo ln -s /usr/bin/nodejs /usr/bin/node
2 有些时候安装源里面没有包含npm包,需要独立安装
sudo apt-get install npm
Tips: 可以使用淘宝的npm镜像,详情请移步 http://npm.taobao.org/
另外还可以从nodejs的官方下载,到https://nodejs.org/download/下载合适的源码包,解压安装
tar -xvf node-v*.tar.gz
./configure
make
sudo make install
1.2、全局安装grunt-cli和bower以及yeoman
sudo npm install -g grunt-cli bower yeoman
- 关于grunt的使用,请移步http://gruntjs.com/getting-started
- 关于bower的使用,请移步http://bower.io/
- 关于yeoman的使用,请移步http://yeoman.io/authoring/index.html
之后安装generator-angular (https://github.com/yeoman/generator-angular)
sudo npm install -g generator-karma generator-angular
1.3、初始化一个angular开发环境
yo angular Test
在这个过程会提示您是否使用sass以及选择angular相关的组建。
这样,一个angular开发环境初始化工作就完成了。
2、如何使用angular构建web app
2.1、建议使用的angular组织结构
▾ app/
▾ common/
▾ dialog/
▸ providers/
▸ templates/
dialogModule.js
▾ form/
▸ directives/
▸ styles/
▸ templates/
formModule.js
▸ rest/
▸ table/
▸ toastr/
▸ tooltips/
▾ container/
▾ config/
router.js
▾ controllers/
containerConsoleController.js
containerController.js
containerCreateController.js
containerDetailController.js
▸ directives/
▾ styles/
container.css
▾ templates/
console.html
container.html
create.html
detail.html
containerModule.js
▸ home/
▸ image/
▸ overview/
▸ pics/
404.html
favicon.ico
index.html
- 如上所示,common包中包含各个提取出来的通用的angular包,每个包包含自己独立的module、directives、filters、services、providers、templates、styles等。这样可以很好的利用angular模块化思想特性,利于抽取common中的包作为多项目的公用包。
- 除开common包,每一个子app如container、image、overview都是一个独立的包,同样包中包含自己独立的module、config、controllers、directives、filters、services、providers、templates、styles,angular提供的函数注入功能可以很好的实现各个子应用之间的隔离与独立。
2.2、关于module的使用
module主要定义这个子app的唯一名称,所依赖的包,如:
angular.module('dockerEasyUiApp',
['overview',
'container',
'image',
'rest',
'table',
'dialog',
'form',
'toastr',
'tooltip',
'ngRoute',
'ngTouch',
'ngAnimate',
'ngResource',
'ngCookies'
]);
2.3、关于config的使用
config一般来说会定义包中一些全局配置,如路由配置
angular.module('container').config(['$routeProvider', '$locationProvider',
function indexRouteConfig($routeProvider, $locationProvider) {
// Disable HTML5 mode (use # for routing)
$locationProvider.html5Mode(false);
var APP_NAME = "Docker easy UI";
// Configure each possible route
$routeProvider
// Container screen
.when('/container', {
title : APP_NAME,
templateUrl : 'container/templates/container.html',
controller : 'containerController'
})
// Image detail screen
.when('/container/:id', {
title : APP_NAME,
templateUrl : 'container/templates/detail.html',
controller : 'containerDetailController'
})
.when('/container/:id/console', {
title : APP_NAME,
templateUrl : 'container/templates/console.html',
controller : 'containerConsoleController'
})
}]);
如http headers配置
/**
* The config block for setting up the HTTP method.
*/
angular.module('dockerEasyUiApp').config(['$httpProvider',
function httpCommonConfig($httpProvider) {
$httpProvider.defaults.headers.common = {
'Content-Type': 'application/json'
}
}]);
2.4、关于services使用
services一般定义的是为controllers服务的方法,如通常web app中的数据源于服务器端,需要走http请求,service端可以是对提供http数据请求的封装,如
angular.module('rest').factory('imageService', ['$injector',
function imageService($injector) {
// Required services
var $http = $injector.get('$http');
// Get required types
var service = {};
/**
* Makes a request to the REST API to get the list of images,
* returning a promise that provides an array of @link{ImageSample} objects if
* successful.
*
* @param {Object.<Stirng, String>} queryOps
* The set of query options to filter with.
*
* @returns {Promise.<ImageSample[]>}
* A promise which will resolve with an array of @link{ImageSample} objects
* upon success.
*/
service.index = function index(queryOps) {
// Retrieve Servers
return $http({
method : 'GET',
url : '/images/json',
params : queryOps
});
};
/**
* Makes a request to the REST API to get image by id,
* returning a promise that provides an @link{ImageSample} object if
* successful.
*
* @param {Object.<Stirng, String>} queryOps
* The set of query options to filter with.
*
* @returns {Promise.<ImageSample>}
* A promise which will resolve with an @link{ImageSample} object
* upon success.
*/
service.show = function show(queryOps) {
// Retrieve Servers
return $http({
method : 'GET',
url : '/images/' + queryOps.id + '/json'
});
};
/**
* Makes a request to the REST API to get image by id,
* returning a promise that provides an @link{ImageSample} object if
* successful.
*
* @param {Object.<Stirng, String>} queryOps
* The set of query options to filter with.
*
* @returns {Promise.<ImageSample>}
* A promise which will resolve with an @link{ImageSample} object
* upon success.
*/
service.search = function search(searchVal) {
// Retrieve Servers
return $http({
method : 'GET',
url : '/images/search?term=' + searchVal
});
};
/**
* Makes a request to the REST API to delete a image,
* returning a promise that provides an Object.<String, String>
* if successful.
*
* @param {String} id
* The id of image.
*
* @returns {Promise.<Object>}
* A promise which will resolve with an object upon success.
*/
service.del = function del(id) {
var url = '/images/' + id;
// Retrieve Servers
return $http({
method : 'DELETE',
url : url
});
};
return service;
}]);
Tips:一般在用组建时,为了保持格式的简洁一致,通畅使用$inject
,然后通过$inject.get(“ServiceName”)
获取想要使用的方法。在定义的依赖里面讲所有的依赖都写出来,显得比较的臃肿,如
angular.module('test').controller('testController', ['$scope', '$http', '$q', '$timeout', '$router','$location'
function imageService($scope, $http, $q, $timeout, $router, $location) {
....
]);
推荐的优雅的方法是
angular.module('test').controller('testController', ['$scope', '$injecteor'
function imageService($scope, $injector) {
var $http = $injector.get("$http");
var $q = $injector.get("$q");
var $timeout = $injector.get("$timeout");
var $router = $injector.get("$router");
var $location = $injector.get("$location");
....
]);
2.5、关于controller使用
controller被定义为view和data交互的中间枢纽,既然是枢纽,所有controller中更应该体现逻辑,如
angular.module('image').controller('imageController', ['$scope', '$injector',
function indexController($scope, $injector) {
// Get image service.
var imageService = $injector.get("imageService");
var $dialog = $injector.get("$dialog");
var $route = $injector.get("$route");
var toastr = $injector.get("toastr");
// Define image table columns.
$scope.imageTableData = {
checkboxHeader: false,
singleSelect: true,
columns: [{
field: 'isSelected',
checkbox: true
}, {
field: 'Id',
title: 'ID',
visible: false
}, {
field: 'NamesLink',
title: 'Repostry Tags',
align: 'left',
valign: 'middle',
sortable: true
}, {
field: 'Size',
title: 'Size',
align: 'right',
valign: 'middle',
sortable: true
}, {
field: 'VirtualSize',
title: 'Virtual Size',
align: 'right',
valign: 'middle',
sortable: true
}, {
field: 'ParentId',
title: 'Parent',
align: 'left',
valign: 'middle'
}, {
field: 'Created',
title: 'Created',
align: 'left',
valign: 'middle',
sortable: true
}],
data: []
};
// Get image list.
imageService.index({all: 0})
.success(function(images) {
angular.forEach(images, function(ele, index) {
images[index].NamesLink = "<a class='' href='#/image/" +
images[index].Id + "'>" + images[index].RepoTags + "</a>";
});
$scope.imageTableData.data = images;
});
// Set image create event.
$scope.AddImage = function AddImage() {
$dialog.open({
templateUrl: 'image/templates/create.html',
controller: 'imageAddController'
});
};
// Handle image delete action.
$scope.Del = function Del(mode) {
if(!$scope.selectedItem) return;
var selectedItem = $scope.selectedItem;
//angular.forEach($scope.selectedItems || [], function(ele) {
imageService.del(selectedItem.Id).success(function (){
$route.reload();
toastr.success("Successfully delete image " + selectedItem.RepoTags);
});
//});
}
}]);
如上,controller更着重于调用服务,处理view的显示以及响应view层的事件逻辑。
Tips:一般说来,不太建议在controller中调用类似于$(selector).method()
这样的方法,angular一个很重要的思路就是让开发者从繁杂的dom对象处理中解脱出来!!!但是也有例外,比如处理一些页面效果时如果使用了jquery插件,可能需要用到$(selector).method()
,但一般这些代码体现在directives中。
2.6、关于filters使用
filter第一为处理view显示的方法,如格式化时间
<div>{{'2012-12-12T12:12:12'|datetime 'YY-MM-DD HH-mm-ss'}}</div>
然后定义一个directive方法处理时间
angular.module('test').filter('datatime', function() {
return function(text) {
// handle time formate.
}
});
Tips:一般说来,不太建议在controller中过多的处理源数据,而是通过定义filter来处理