首先,我们来看一下工程结构目录:
我们可以看到scripts中分列了一下几个文件夹:controllers、services、directives、filters、vendor,以及两个文件app.js和main.js。
controllers里面主要就是控制器
services里面是服务,为控制器提供数据服务支持,与后台交互的代码就在其中
directives是指令,用于生成自定义标签的html模板
filters是过滤器,用于处理显示数据的形式
vendor文件夹中存放的是引用的第三方js插件
跟scripts同级的是styles和views文件夹,styles存放css样式文件,view存放html文件。
我们先来看一下index.html中的主要代码:
<!DOCTYPE html>
<html> <!-- Do not add ng-app here as we bootstrap AngularJS manually-->
<head>
<title>My AngularJS App</title>
<meta charset="utf-8" />
<link rel="stylesheet" type="text/css"
href="styles/bootstrap.min.css">
<link rel="stylesheet" type="text/css" href="styles/ng-grid.css" />
<link rel="stylesheet" type="text/css" href="styles/main.css">
</head>
<body class="home-page row-fluid">
<nav class="navbar navbar-default">
……
</nav>
<div class="col-lg-10 col-md-12 col-sm-12 col-sm-12 col-lg-offset-1">
<div ng-view></div>
</div>
<div class="row-fluid">
</div>
<script data-main="scripts/main"
src="scripts/vendor/require.js"></script>
</body>
</html>
我们可以看到导入的js只有一个require.js,但是这个script中有个这样的属性
data-main="scripts/main"
这个属性就将主js指向了scripts/main.js。
下面来看main.js,其中,分为了两块,第一块是对第三方的引用和依赖配置:
// the app/scripts/main.js file, which defines our RequireJS config
require.config({
paths:{
angular:'vendor/angular.min',
jquery:'vendor/jquery',
bootstrap:'vendor/bootstrap.min',
domReady:'vendor/domReady',
ngGrid:'vendor/ng-grid.debug'
},
shim:{
angular:{
deps:[ 'jquery'],
exports:'angular'
},
ngGrid:{
deps:[ 'jquery']
},
bootstrap:{
deps:[ 'jquery']
}
}
});
第二块就是主要的引用和route信息了:
require([
'angular',
'app',
'domReady',
'bootstrap',
'services/userService',
'controllers/rootController',
'directives/ngbkFocus',
'controllers/user/listController',
'controllers/user/editController',
'controllers/user/newController',
'ngGrid'
// Any individual controller, service, directive or filter file
// that you add will need to be pulled in here.
],
function (angular, app, domReady) {
'use strict';
app.config(['$routeProvider',
function ($routeProvider) {
$routeProvider.when('/', {
templateUrl:'views/user/list.html',//当跳转到该路径时,将此html嵌入到ng-view属性的dom中
controller:'ListCtrl'//当前templateUrl的controller为ListCtrl
})
.when('/edit/:name/:allowance', {
templateUrl:'views/user/form.html',
controller:'EditCtrl'
})
.when('/new', {
templateUrl:'views/user/form.html',
controller:'NewCtrl'
})
.when('/root', {
templateUrl:'views/root.html',
controller:'RootCtrl'
});
}
]);
domReady(function () {
angular.bootstrap(document, ['MyApp']);//app名为MyApp
// The following is required if you want AngularJS Scenario tests to work
$('html').addClass('ng-app: MyApp');//给html添加ng-app属性
});
}
);
以list的route为示例,我们来讲解controller,先看一张list效果图(此处我们引用了ng-grid插件):
我们来看引入的controllers/user/listController:
define(['controllers/controllers', 'services/userService'],
function (controllers) {
controllers.controller('ListCtrl', ['$scope', '$http', '$location', 'UserService',//此处数组中的参数依次对应下面回调方法中的参数
function ($scope, $http, $location, UserService) {
$scope.mySelections = [];
$scope.filterOptions = {
filterText:"",
useExternalFilter:true
};
$scope.totalServerItems = 0;
$scope.pagingOptions = {
pageSizes:[250, 500, 1000],
pageSize:250,
currentPage:1
};
$scope.setPagingData = function (data, page, pageSize) {
var pagedData = data.slice((page - 1) * pageSize, page * pageSize);
$scope.myData = pagedData;
$scope.totalServerItems = data.length;
if (!$scope.$$phase) {
$scope.$apply();
}
};
$scope.getPagedDataAsync = function (pageSize, page, searchText) {
setTimeout(function () {
var data;
if (searchText) {
var ft = searchText.toLowerCase();
UserService.getServerData(function (largeLoad) {
data = largeLoad.filter(function (item) {
return JSON.stringify(item).toLowerCase().indexOf(ft) != -1;
});
$scope.setPagingData(data, page, pageSize);
});
} else {
UserService.getServerData(function (largeLoad) {
$scope.setPagingData(largeLoad, page, pageSize);
});
}
}, 100);
};
$scope.getPagedDataAsync($scope.pagingOptions.pageSize, $scope.pagingOptions.currentPage);
$scope.$watch('pagingOptions', function (newVal, oldVal) {
if (newVal !== oldVal && newVal.currentPage !== oldVal.currentPage) {
$scope.getPagedDataAsync($scope.pagingOptions.pageSize, $scope.pagingOptions.currentPage, $scope.filterOptions.filterText);
}
}, true);
$scope.$watch('filterOptions', function (newVal, oldVal) {
if (newVal !== oldVal) {
$scope.getPagedDataAsync($scope.pagingOptions.pageSize, $scope.pagingOptions.currentPage, $scope.filterOptions.filterText);
}
}, true);
$scope.clickme = function (v) {
$location.path('/edit/' + v.name + "/" + v.allowance);
}
$scope.gridOptions = {
data:'myData',
enablePaging:true,
showFooter:true,
totalServerItems:'totalServerItems',
pagingOptions:$scope.pagingOptions,
filterOptions:$scope.filterOptions,
selectedItems:$scope.mySelections,
showSelectionCheckbox:true,
columnDefs:[
{ field:"name", pinned:true }
,
{ field:"allowance", cellTemplate:'<div class="ngCellText" ng-class="col.colIndex()"><span ng-cell-text>{{COL_FIELD | currency}}</span></div>'}
,
{ field:"entity", pinned:true, cellTemplate:'<div class="ngCellText" ng-class="col.colIndex()"><span ng-cell-text>{{$parent.row.entity | myfilter}}</span></div>' }
,
{ field:"name", width:100, cellTemplate:'<button class="btn-xs table-btn" ng-click="clickme($parent.row.entity)"><span class="glyphicon glyphicon-search" aria-hidden="true"></span></button>'}
]/*,
multiSelect:false*/
};
}]);
});
其中定义了该controller名为ListCtrl,$scope为局部变量,其中定义的数据与方法可在当前Ctrl作用域内生效,我们来看一下生效的list.html是怎么样的
<div class="gridStyle" ng-grid="gridOptions"></div>
就是这么一句话,定义了grid的div,其余的都交给了controller和ng-grid插件
listController中引用了services/userService,service层用来与后台交互,管理数据:
define(['services/services'],
function (services) {
services.factory('UserService', ['$http',
function ($http) {
return {
getData:function () {
return [
{ name:"Moroni", age:50, birthday:"Oct 28, 1970", salary:"60,000" },
{ name:"Tiancum", age:43, birthday:"Feb 12, 1985", salary:"70,000" },
{ name:"Jacob", age:27, birthday:"Aug 23, 1983", salary:"50,000" },
{ name:"Nephi", age:29, birthday:"May 31, 2010", salary:"40,000" },
{ name:"Enos", age:34, birthday:"Aug 3, 2008", salary:"30,000" },
{ name:"Moroni", age:50, birthday:"Oct 28, 1970", salary:"60,000" },
{ name:"Tiancum", age:43, birthday:"Feb 12, 1985", salary:"70,000" },
{ name:"Jacob", age:27, birthday:"Aug 23, 1983", salary:"40,000" },
{ name:"Nephi", age:29, birthday:"May 31, 2010", salary:"50,000" },
{ name:"Enos", age:34, birthday:"Aug 3, 2008", salary:"30,000" },
{ name:"Moroni", age:50, birthday:"Oct 28, 1970", salary:"60,000" },
{ name:"Tiancum", age:43, birthday:"Feb 12, 1985", salary:"70,000" },
{ name:"Jacob", age:27, birthday:"Aug 23, 1983", salary:"40,000" },
{ name:"Nephi", age:29, birthday:"May 31, 2010", salary:"50,000" },
{ name:"Enos", age:34, birthday:"Aug 3, 2008", salary:"30,000" }
];
},
getOptions:function () {
return {
data:'myData',
enablePinning:true,
columnDefs:[
{ field:"name", width:120, pinned:true },
{ field:"age", width:120 },
{ field:"birthday", width:120 },
{ field:"salary", width:120 }
]
}
},
getServerData:function (success) {
$http.get('jsonFiles/largeLoad.json').success(success);
},
saveData:function (data, success) {
$http.post('/users/save', data).success(success);
}
};
}]);
});
其中引用的$http是用来管理ajax的对象,类似的对象还有$location,用来管理url地址,类似的对象还有很多,详细可以参见官方API文档。
至此,一个前端MVC框架基本构建完成,在之后的一篇中我们来着重介绍下还没讲过的filters和directives。
亿速云「云服务器」,即开即用、新一代英特尔至强铂金CPU、三副本存储NVMe SSD云盘,价格低至29元/月。点击查看>>
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。