Angularjs开发CRUD类型的Web系统生产力惊人,与jQuery,YUI,kissy,Extjs等前端框架区别很是大,初学者在学习的过程当中容易以本身以往的经验来学习Angularjs 每每走入误区,最典型的特征是在的开发过程当中,使用大量的 指令(directive) 来实现许多操做DOM的功能,从而失去了angularjs快速开发的特性,最后不得不放弃使用。此系列的文章并不会像其余介绍Angularjs技术文档同样将每一个技术细节通通照顾到,而是经过实战项目先让初学者有个大概的了解,而后你们在由浅入深逐渐熟悉每个细节。
javascript
Github Angularjs
写此博客的时候angularjs官方稳定版已经更新到 “1.4.2”,内部测试版更新到“2.0.0-alpha.30”
本篇博客使用angularjs 1.4.2 版本
angularjs 1.4.2下载地址css
首先放一个招牌Demo:html
<!--设置angularjs在页面上的访问域--> <html ng-app="Yiim"> <head> <meta name="viewport" content="width=device-width" /> <title>Index</title> <script src="http://files.cnblogs.com/files/Arrays/angular.min.js"></script> <script type="text/javascript"> //声明一个私有函数域 (function () { //建立一个app模块(你就想象成C#里面的一个类库吧) var app = angular.module("Yiim", []); //在app模块中建立一个"tmplController"控制器 app.controller("tmplController", ["$scope", function ($scope) { //设置(val)变量值 $scope.val = "Google是最棒的搜索引擎。"; }]); })() </script> </head> <body> <!--设置当前div的控制器为"tmplController"--> <div ng-controller="tmplController"> <div>{{val}}</div> </div> </body> </html>
点击此运行前端
顾名思义,只使用一个页面的Web应用程序.单页面应用是指用户经过浏览器加载独立的HTML页面,Ajax加载数据页面无刷新,实现操做各类操做。java
这里的模板是指前端模板,在angularjs 以外已经有很是丰富的JavaScript模板引擎了,例如artTemplate,Mustache,doT.js等。
Angularjs 内置有本身的模板引擎。
经过下面的DEMO咱们一块儿了解一下Angularjs 内置模板引擎:jquery
<!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <title>angularjs 模板解释</title> <script src="http://files.cnblogs.com/files/Arrays/angular.min.js"></script> <script type="text/javascript"> //声明一个私有函数域 (function () { var app = angular.module("Yiim", []); //建立模块 app.controller("tmplController", ["$scope", function ($scope) { //给变量val赋值 $scope.val = "Google是最好的搜索引擎"; //给变量list赋值 $scope.list = [ { title: "博客园", url: "http://www.cnblogs.com" }, { title: "知乎", url: "http://www.zhihu.com" }, { title: "codeproject", url: "http://www.codeproject.com/" }, { title: "google", url: "http://www.google.com/" } ] //给变量hasValue赋值 $scope.hasValue = false; }]); })() </script> </head> <body ng-app="Yiim"> <div ng-controller="tmplController"> <!--普通输出--> <div>{{val}}</div> <!--循环--> <ul ng-repeat="item in list"> <li><a href="{{item.url}}" rel=nofollow>{{item.title}}</a></li> </ul> <!--条件语句--> <div ng-if="!hasValue"> Angularjs条件语句 </div> </div> </body> </html>
点击此运行git
以上代码首先建立一个"Yiim"模块,而后在模块中添加了一个名词为"tmplController"的控制器,而后给scope添加三个属性“val”,“list”,“hasValue”,并赋值。
在模板页面设置angularjs做用域为"body"标签内,名词为"Yiim"angularjs
<body ng-app="Yiim">
在做用域中设置控制器为"tmplController"github
<div ng-controller="tmplController">
例子中提供了3种输出方式(普通输出,循环,条件语句),固然angularjs不只仅这几种方式
“ng-repeat”,“ng-if” 这都是经过指令实现。咱们在下一节(2.5 )将详细讲解web
控制器能够理解为控制页面某个区块的方法。其中有一个很是重要的对象 $scope是这个控制器与页面控制器区域沟通的桥梁。angularjs最精华的部分是双向绑定,失去了双向绑定angularjs就失去了本身的灵魂。这也是和其余以DOM操做的框架比最大的区别。放DEMO
<!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <title>angularjs控制器介绍</title> <script src="http://files.cnblogs.com/files/Arrays/angular.min.js"></script> <script type="text/javascript"> (function () { var app = angular.module("Yiim", []); app.controller("cntoController", ["$scope", function ($scope) { var defaults = "知乎 - 与世界分享你的知识、经验和看法"; //设置值 $scope.val = defaults; $scope.click = function () { $scope.val = defaults; }; }]); })() </script> </head> <body ng-app="Yiim"> <div ng-controller="cntoController"> <!--绑定值--> <div><textarea ng-model="val"></textarea></div> <!--输出值--> <div>{{val}}</div> <!--绑定方法--> <div><button ng-click="click()">重置</button></div> </div> </body> </html>
控制器演示效果 点击此运行
与2.2节例子相同是,咱们首先建立了一个模块,而后在模块中添加一个控制器方法 "cntoController".
在控制器里咱们给scope添加了一个属性"val" 和一个方法 "click"。
在页面中咱们使用"ng-model"指令绑定控制器中设置的"val"
<div><textarea ng-model="val"></textarea></div>
紧接着咱们把绑定的值输出处理
<div>{{val}}</div>
经过内置的绑定方法click 咱们重置字符串
$scope.click = function () { $scope.val = defaults; };
单页Web应用因为没有后端URL资源定位的支持,须要本身实现URL资源定位。angularjs使用浏览器URL "#" 后的字符串来定位资源,区分不一样的功能模块。
路由并不是在angularjs核心文件内,你须要另外加入一段脚本 “angular-route.min.js”
须要注意的是在建立 “app” 对象是须要填写对 ngRoute 依赖
var app = angular.module("Yiim", ['ngRoute']);//注意 ngRoute
下面咱们一样的展现一个demo
主页面 route.html
<!DOCTYPE html> <html ng-app="Yiim" xmlns="http://www.w3.org/1999/xhtml"> <head> <title>angularjs路由介绍</title> <script src="http://files.cnblogs.com/files/Arrays/angular.min.js"></script> <script src="http://files.cnblogs.com/files/Arrays/angular-route.min.js"></script> <script type="text/javascript"> //声明一个私有函数域 (function () { //设置当前模块依赖,“ngRoute”,用.NET的理解就是给这个类库添加“ngRoute”引用 var app = angular.module("Yiim", ['ngRoute']); //配置路由 app.config(['$routeProvider', function ($routeProvider) { var route = $routeProvider; //指定URL为“/” 控制器:“indexController”,模板:“route.html” route.when('/list', { controller: 'listController', templateUrl: 'route-list.html' }); //注意“/view/:id” 中的 “:id” 用于捕获参数ID route.when('/view/:id', { controller: 'viewController', templateUrl: 'route-view.html' }); //跳转 route.otherwise({ redirectTo: '/list' }); }]); //建立一个提供数据的服务器 app.factory("service", function () { var list = [ { id: 1, title: "博客园", url: "http://www.cnblogs.com" }, { id: 2, title: "知乎", url: "http://www.zhihu.com" }, { id: 3, title: "codeproject", url: "http://www.codeproject.com/" }, { id: 4, title: "google", url: "http://www.google.com/" } ]; return function (id) { //假如ID为无效值返回全部 if (!id) return list; var t = 0; //匹配返回的项目 angular.forEach(list, function (v, i) { if (v.id == id) t = i; }); return list[t]; } }) //建立控制器 indexController app.controller("listController", ["$scope", "service", function ($scope, service) { //获取全部数据 $scope.list = service(); }]); //建立查看控制器 viewController, 注意应为须要获取URL ID参数 咱们多设置了一个 依赖注入参数 “$routeParams” 经过它获取传入的 ID参数 app.controller("viewController", ["$scope", "service", '$routeParams', function ($scope, service, $routeParams) { $scope.model = service($routeParams.id || 0) || {}; }]) })() </script> </head> <body> <div><a href="#/list">列表</a></div> <div ng-view> </div> </body> </html>
列表页面 route-list.html
<ul ng-repeat="item in list"> <li><a href="#view/{{item.id}}">{{item.title}}</a></li> </ul>
详细页面 route-view.html
<div> <div>网站ID:{{model.id}}</div> <div>网站名称:<a href="{{model.url}}" rel="nofollow">{{model.title}}</a></div> <div>访问地址:{{model.url}}</div> </div>
演示效果:点击此运行
以上代码中,咱们首先配置了三条个处理个局部页面的路由
路由处理列表页并设置控制器为"listController",指定模板页为"route-list.html"
route.when('/list', { controller: 'listController', templateUrl: 'route-list.html' });
与上面不一样的是第二条路由中包含":id"用于捕获URL后面的参数 。
route.when('/view/:id', { controller: 'viewController', templateUrl: 'route-view.html' });
处理全部未匹配到的路由跳转到 "'/list'"内。
route.otherwise({ redirectTo: '/list' });
咱们还使用了模块方法 "factory" 建立一个"service" 服务,用于获取数据列表
后面咱们声明了两个控制器"listController","viewController",同时配置对"service"的依赖,"viewController" 中咱们还添加对 "$routeParams" 的依赖,用于获取路由捕获的id。
须要注意的是咱们再主页面声明了"ng-view"用于指定局部页面和控制器做用范围。
<div ng-view></div>
指令(directive)并非什么高深的东西,咱们简单理解为经过声明 特殊的标签,属性..等来处理浏览器没法渲染的功能。经过JavaScript将指令替换成浏览器能够识别的标签。
当前这不是它存在的惟一意义。在上面的例子中咱们已经见到了“ng-if”,"ng-repeat"等这些angularjs 内置的指令。固然咱们也能够定义本身使用的指令。
<!DOCTYPE html> <html ng-app="Yiim" xmlns="http://www.w3.org/1999/xhtml"> <head> <title>angularjs指令演示</title> <script src="//cdn.bootcss.com/jquery/2.1.4/jquery.js"></script> <script src="http://files.cnblogs.com/files/Arrays/angular.min.js"></script> <script type="text/javascript"> //声明一个私有函数域 (function () { var app = angular.module("Yiim", []); //建立一个提供数据的服务器 app.factory("service", function () { var list = [ { id: 1, title: "博客园", url: "http://www.cnblogs.com" }, { id: 2, title: "知乎", url: "http://www.zhihu.com" }, { id: 3, title: "codeproject", url: "http://www.codeproject.com/" }, { id: 4, title: "google", url: "http://www.google.com/" } ]; return function (id) { //假如ID为无效值返回全部 if (!id) return list; var t = 0; //匹配返回的项目 angular.forEach(list, function (v, i) { if (v.id == id) t = i; }); return list[t]; } }) //建立指令imCheck 在HTML中的语法为 im-check app.directive("imCheck", [function () { return { restrict: 'A', replace: false, link: function (scope, element) { var all = "thead input[type='checkbox']"; var item = "tbody input[type='checkbox']"; //当点击选择全部事便利全部项目 element.on("change", all, function () { var o = $(this).prop("checked"); var tds = element.find(item); tds.each(function (i, check) { $(check).prop("checked", o); }); }); //子项修改时的超值 element.on("change", item, function () { var o = $(this).prop("checked"); var isChecked = true; if (o) { element.find(item).each(function () { if (!$(this).prop("checked")) { isChecked = false; return false; } return true; }); } element.find(all).prop("checked", o && isChecked); }); } }; }]) app.controller("dectController", ['$scope', 'service', function ($scope, service) { $scope.list = service(); }]) })(); </script> </head> <body> <!--注意一下标签 im-check 指定使用的指令--> <table ng-controller="dectController" im-check> <thead> <tr> <th><input type="checkbox">选择</th> <th>网站ID</th> <th>网站名称</th> <th>连接地址</th> </tr> </thead> <tbody> <tr ng-repeat="item in list"> <td><input type="checkbox"></td> <td>{{item.id}}</td> <td>{{item.title}}</td> <td>{{item.url}}</td> </tr> </tbody> </table> </body> </html>
演示效果 点击此运行
上面的例子中,咱们使用模块建立了一个指令"imCheck",并在指令方法"link"注册了使用当前指令的dom对象注册了两个delegate方法 处理全选和子选择项状态改变处理的方法。
"imCheck" 对应在html页面的属性为 "im-check" 注意大小写。
<table ng-controller="dectController" im-check>
还要注意的是咱们使用了jQuery来操做dom节点。
模块化开发不是什么新鲜的概念,后端开发过程当中包,类库这些把功能相近的东西放在一块儿。前端开发很长一段时间混乱无比,脚本之间的冲突,依赖,变量函数覆盖各类奇奇怪怪的问题。模块化开发在前端的定义:将功能相近的组件封装到一块,经过前端依赖注入解决依赖顺序和变量做用域的问题. 表明框架有Seajs,Requirejs。
使用模块化编程实现angularjs多种模块,解决依赖问题
<!DOCTYPE html> <html ng-app="Yiim" xmlns="http://www.w3.org/1999/xhtml"> <head> <title>angularjs 模块化开发</title> <script src="http://files.cnblogs.com/files/Arrays/angular.min.js"></script> <script type="text/javascript"> //声明一个私有函数域 (function () { //建立一个Yiim.service 模块 var service = angular.module("Yiim.service", []); //建立一个Yiim.controller 模块 var controller = angular.module("Yiim.controller", []); //指令模块 var directive = angular.module("Yiim.directive", []); //过滤器模块 var filter = angular.module("Yiim.filter", []); //Yiim.service添加一个服务 service.factory("service", [function () { return { key: "Service" }; }]); //Yiim.controller添加一个控制器 controller.controller("indexController", ['$scope', 'service', function ($scope, service) { $scope.service = service; }]); //获取依赖 var app = angular.module("Yiim", ['Yiim.service', 'Yiim.controller', 'Yiim.directive', 'Yiim.filter']); })(); </script> </head> <body> <div ng-controller="indexController">{{service.key}}</div> </body> </html>
angularjs过滤器,用来格式化数据(转化,排序,筛选等操做)。
<!DOCTYPE html> <html ng-app="Yiim" xmlns="http://www.w3.org/1999/xhtml"> <head> <title>angularjs 过滤器</title> <script src="http://files.cnblogs.com/files/Arrays/angular.min.js"></script> <script type="text/javascript"> //声明一个私有函数域 (function () { var app = angular.module("Yiim", []); app.controller("namesController", ["$scope", function ($scope) { $scope.names = [ { "Name": "Alfreds Futterkiste", "City": "Berlin", "Country": "Germany" }, { "Name": "Berglunds snabbköp", "City": "Luleå", "Country": "Sweden" }, { "Name": "Centro comercial Moctezuma", "City": "México D.F.", "Country": "Mexico" }, { "Name": "Ernst Handel", "City": "Graz", "Country": "Austria" }, { "Name": "FISSA Fabrica Inter. Salchichas S.A.", "City": "Madrid", "Country": "Spain" }, { "Name": "Galería del gastrónomo", "City": "Barcelona", "Country": "Spain" }, { "Name": "Island Trading", "City": "Cowes", "Country": "UK" }, { "Name": "Königlich Essen", "City": "Brandenburg", "Country": "Germany" }, { "Name": "Laughing Bacchus Wine Cellars", "City": "Vancouver", "Country": "Canada" }, { "Name": "Magazzini Alimentari Riuniti", "City": "Bergamo", "Country": "Italy" }, { "Name": "North/South", "City": "London", "Country": "UK" }, { "Name": "Paris spécialités", "City": "Paris", "Country": "France" }, { "Name": "Rattlesnake Canyon Grocery", "City": "Albuquerque", "Country": "USA" }, { "Name": "Simons bistro", "City": "København", "Country": "Denmark" }, { "Name": "The Big Cheese", "City": "Portland", "Country": "USA" }, { "Name": "Vaffeljernet", "City": "Århus", "Country": "Denmark" }, { "Name": "Wolski Zajazd", "City": "Warszawa", "Country": "Poland" } ]; }]) })() </script> </head> <body> <div ng-controller="namesController"> <p>输入过滤:</p> <p><input type="text" ng-model="name"></p> <ul> <li ng-repeat="x in names | filter:name | orderBy:'Country'"> {{ (x.Name | uppercase) + ', ' + x.country }} </li> </ul> </div> </body> </html>
演示效果 点击此运行
咱们使用angularjs内置的过滤器 "filter","orderBy"。
x in names | filter:name | orderBy:'Country'
含义为将集合 "names" 传入过滤器 "filter"匹配字符串为"name"的项目,而后将匹配后的集合传入 "orderBy"过滤器,以"Country"属性进行排序。
在输出变量时咱们使用"uppercase"过滤器转化大小写
x.Name | uppercase