一、前言
对于前端系列,引入AngularJs是必然的。在上一篇文章中,我们介绍了如何使用KnockoutJs创建单页程序,下一篇文章将介绍如何使用AngularJs开发单页应用程序。在开始使用AngularJs开发SPA之前,我觉得有必要详细介绍一下AngularJs涉及的知识点。他们都有这篇文章。
二、AngularJs介绍
AngularJS是谷歌推出的一个Web应用开发框架。它提供了一系列兼容和可扩展的服务,包括数据绑定、DOM操作、MVC和依赖注入。相信下面的图片可以更好的解释AngularJs支持哪些功能。
从上图可以发现,AngularJs几乎支持构建Web应用的所有内容,比如——数据绑定、表单验证、路由、依赖注入、控制器、模板和视图。
但并不是所有的应用都适合AngularJs。AngularJS主要考虑构建凝乳应用程序,但至少90%的Web应用程序是凝乳应用程序。什么不适合AngularJs?游戏和图像界面编辑器等应用不适合AngularJs。
三、AngularJS核心知识点
接下来,我们将详细介绍AngularJS的几个核心知识点,包括:
指令和数据绑定模板(模块)控制器路由服务过滤器)3.1指令和数据绑定
在不使用AngularJs的Web应用中,要实现前台页面逻辑,需要为HTML元素设置ID,然后使用Js或Jquery通过ID获取HTML DOM元素。AngularJS不再需要为HTML元素设置ID,而是使用指令来指导HTML元素的行为。这样做的好处是,当开发人员看到HTML元素和Directive时,可以理解他们的行为。但是传统的设置Id的方式并不能给你带来任何有用的信息,所以你需要深入相应的Js代码去了解它的行为。
以上介绍了这么多,但好像没有正式介绍。说明是什么?引入指令的好处不同于传统方式。指令可以理解为声明特殊的标签或属性。AngularJs有很多内置指令,你看到的所有标签都以ng开头,比如ng-app、ng-init、ng-if、ng-model等等。
Ng-app:用于识别页面是AngularJs页面。一般加载在HTML的根对象上。Ng-init用于初始化变量ng-model:用户在Property和Html控件之间建立双向数据绑定。这样,Html控件的值变化就会反映在Property中,反之亦然。AngularJs通过表达式将数据绑定到HTML标签中。AngularJs的表达式是用双大括号写的:{{expression}}
让我们看一个指令的例子:
!DOCTYPE html html ng-app xmlns=' http://www . w3 . org/1999/XHTML ' head meta http-equiv=' Content-Type ' Content=' text/html;charset=utf-8 '/title使用指令和数据绑定语法/title/headsdy ng-init=' name='欢迎使用angular js'' div name:输入类型=' text ' ng-model=' name '/{ { name } }/div script src=' http 3360/scripts/angular . min . js '/script/body/html当我们更改输入框的值时,相应的更改将反映在name属性中,从而反映表达式的值。AngularJs中双向绑定的使用主要是通过ng-model指令完成的。上面提到的所有指令都是AngularJs的内置指令。其实我们也可以定制说明书。这一部分将在后面介绍。
3.2模板
Asp.net MVC中有两种页面渲染模板,一种是Aspx,另一种是Razor。然而,Asp.net MVC中的这两种模板都是后端模板,即页面渲染是在服务器端完成的。这将不可避免地增加服务器端的压力。AngularJs的模板是指前端模板。AngularJS内置了前端模板引擎,即所有的页面渲染操作都在浏览器端进行渲染,这也是SPA程序的一个优势。所有前端框架都内置了前端模板引擎,在前端呈现页面,从而减轻了服务器端的压力。
AngularJs中的模板引用带有ng-app说明的HTML代码。AngularJs发现Html页面是否需要由AngularJs模板引擎呈现的标志是ng-app标记。
在AngularJs中,我们写的不是一个纯粹的Html页面,而是一个模板。最终用户看到的Html页面(即视图)是通过模板呈现的结果。
让我们看一个模板的例子:
!DOCTYPE html html ng-app=' mainApp ' head meta http-equiv=' Content-Type ' Content=' text/html;charset=utf-8 '/title template Demo/title Script src=' http :3358 sandbox . run js.cn/uploads/RS/376/pbcx3e 1z/angular . min . js '/Script Script(function(){//create module var main app=angular . module(' main app ',[]);//创建控制器并注入作用域主应用。控制器(' temp controller ',['$ scope ',function ($ scope) {$ scope。欢迎学习angular js。}]);})()/script/head body H2 angular js模块演示/H2 div ng-controller=' temp controller ' div输入类型=' text ' ng-model=' val ' { val } }/div/div/body/html 3.3 controller
实际上,在模板的例子中,我们已经定义了一个名为“tempController”的控制器。接下来,我们将详细介绍AngularJs中的控制器。实际上,AngularJs中控制器的功能与Asp.net MVC中的相同,是模型和视图之间的桥梁。AngularJs的模型对象是$scope。因此,AngularJs控制器知道$scope和view之间的桥梁,它通过操作$scope对象来改变视图。下面的代码演示了控制器的使用:
!DOCTYPE html html ng-app=' mainApp ' head meta http-equiv=' Content-Type ' Content=' text/html;charset=utf-8 '/title anglarjs控制器演示/title Script src=' http :http://sandbox.runjs.cn/uploads/RS/376/pbcx3e1z/angular.min.js'/脚本脚本(function(){//create module var mainapp=angular . module(' mainapp ',[]));main app . controller(' cntocontroller ',['$ scope ',function ($ scope) {var默认值='学习硬前端系列';$ scope.val=defaultValue$ scope . click=function(){ $ scope . val=DefaultValue;};}]);})()/脚本/headbody H2 angular js控制器演示/H2 div ng-controller=' cntocontroller ' div textarea ng-model=' val '/textarea/div div { { val } }/div div按钮ng-click=' click()' reset/button/div/body/html
AngularJs框架=MVC MVVM的原因是因为AngularJs除了双向绑定之外还支持路由(也就是MVVM特性)。在前面介绍的由KnockoutJs实现的SPA中,借用了Asp.net MVC中的路由机制。有了AngularJs,我们可以用AngularJs框架代替Asp.net MVC。
单页Web应用由于不具备后端URL资源定位的支持,需要实现URL资源定位。AngularJs使用浏览器URL“#”后面的字符串来定位资源。路由机制不在AngularJS的核心文件中,所以需要添加angular-route.min.js的脚本并且在创建mainApp模块时,需要添加对ngRoute的依赖。
让我们具体看一个路由的例子,感受路由在AngularJs中的使用。具体示例代码如下:
主页AngularJsRouteDemo.html
!DOCTYPE html html ng-app=' mainApp ' xmlns=' http://www。w3。org/1999/XHTML ' head meta http-equiv=' Content-Type ' Content=' text/html;charset=utf-8 '/title anglarjs路由演示/title脚本src=' http :http://沙箱。runjs。cn/uploads/RS/376/pbcx3e 1z/angular。量滴js '/script script src=' http :http://沙箱。runjs。cn/uploads/RS/376/pbcx3e 1z/angular-route。量滴js '/script(function(){//设置当前模块依赖、“ngRoute”,用。网的解就是给这个类库添加" ngRoute "引用var主app=angular。模块(' main app ',[' ngRoute ']);mainapp。config([' $ RouterProvider ',function($ RouterProvider){//路由配置var route=$ routeProvider//指定统一资源定位器为"/" 控制器:"列表控制器",模板:“路由列表。html "路由。当('/list ',{ controller : ' list controller ',模板URL : ' route-list。html ' });//注意"/view/:id "中的":id "用于捕获参数ID route.when('/view/:id ',{ controller : ' view controller ',模板URL : ' route-view '。html ' });//跳转route.when('/',{ redirectto : '/list ' });路线。无({ redirectto : '/list ' });}]);//创建一个提供数据的服务器mainApp.factory('service ',function() { var list=[ { id: 1,title: '博客园,网址: ' http://www。cn博客。com ' },{ id: 2,title: '知乎,url: 'http://www.zhihu.com' },{ id: 3,title: 'codeproject ',url: 'http://www。代码项目。com/' },{ id: 4,title: 'stackoverflow ',URL : ' http://www。堆栈溢出。com/' };返回函数(id) { //假如身份为无效值返回所有if(!id)返回列表;var t=0;//匹配返回的项目angular.forEach(list,function(v,I){ if(v . id==id)t=I;});返回列表[t];} });//创建控制器列表控制器,注入提供数据服务mainapp。controller(' listController ',['$scope ',' service ',function($scope,service) { //获取所有数据$ scope。list=service();}]);//创建查看控制器视图控制器,注意应为需要获取网址标识参数我们多设置了一个依赖注入参数" $ routeParams "通过它获取传入的身份参数mainapp。controller(' view controller ',['$scope ',' service ',' $ routeParams ',function($scope,service,$ route params){ $ scope。模型=服务($ route params)。id | | 0)| | { };}]);})()/脚本/头体diva href=' #/list '列表/a/div br/div ng-view/div/body/html列表页面route-list.html
ul ng-repeat='列表中的项目lia href=' # view/{ { item。id } } ' { { item。title } }/a/Li/ul详细页面route-view.html
差异网站ID:{{model.id}}/div div网站名称:a href=' { { model。URL } } ' rel='无跟随' { model。标题} }/a/div访问地址:{ { model。网址} }/div/div
3.5 自定义指令
前面我们已经介绍过指令了。除了AngularJs内置的指令外,我们也可以自定义指令来供我们程序使用。
如果我们在程序中需要对数字正射影像图操作的话,我们可以使用指令来完成。下面让我们来看下一个全选复选框的自定义指令的实现:
!DOCTYPE html html ng-app=' mainApp ' xmlns=' http://www。w3。org/1999/XHTML ' head meta http-equiv=' Content-Type ' Content=' text/html;charset=utf-8 '/title anglarjs指令演示/title脚本src=' http :http://沙箱。运行js。cn/uploads/RS/376/pbcx3e 1z/jquery-1。10 .2 .量滴js '/script script src=' http :http://沙箱。运行js。cn/uploads/RS/376/pbcx3e 1z/angular。量滴js '/script script(function(){ var mainApp=angular。模块(' mainApp ',[]);//创建一个提供数据的服务器mainApp.factory('service ',function () { var list=[ { id: 1,title: '博客园,网址: ' http://www。cn博客。com ' },{ id: 2,title: '知乎,url: 'http://www.zhihu.com' },{ id: 3,title: 'codeproject ',url: 'http://www。代码项目。com/' },{ id: 4,title: 'stackoverflow ',URL : ' http://www。堆栈溢出。com/' };返回函数(id) { //假如身份为无效值返回所有if(!id)返回列表;var t=0;//匹配返回的项目angular.forEach(list,function (v,I){ if(v . id==id)t=I;});返回列表[t];};});mainApp.directive('imCheck ',[function(){ return { restrict : ' A ',replace: false,link: function(作用域,元素){ var all=' and input[type=' checkbox ']';var item=' t body input[type=' checkbox ']';//当点击选择所有项目element.on('change ',all),function () { var o=$(this).道具('选中');var TDS=元素。find(item);tds .每个(函数(我,支票){ $(支票)).道具('已检查,o);});});//子项修改时的超值element.on('change ',item,function () { var o=$(this).道具('选中');var Ischecked=true if(o){ element . find(item).每个(函数(){ if(!$(这个)。prop(' checked '){ isChecked=false;返回false}返回true });} element.find(all).道具('选中,o isChecked);});} };}]);mainapp。控制器(' dectController ',['$scope ',' service ',函数($scope,service){ $ scope。list=service();}]);})()/脚本/头体h2AngularJs指令演示/h2表ng-控制器=' dect控制器' im-检查输入类型='复选框'选择/th网站第/次网站名称/th链接地址/th/tr/TD t车身tr ng-repeat='列表中的项目t输入类型=' checkbox '/TD TD { { item }。id } }/TD { { item }。title } }/TD { { item。网址} }/TD/tr/t正文/表格/正文/html
3.6 服务
在上面的路由例子和自定义指令中都有用到AngularJs中的服务。我理解AngularJs的服务主要是封装请求数据的内容。就如。网解决方案的层次结构中的服务层。然后AngularJs中的服务一个很重要的一点是:服务是单例的。一个服务在AngularJS应用中只会被注入实例化一次,并贯穿整个生命周期,与控制器进行通信。即控制器操作$范围对象来改变视图,如果控制器需要请求数据的话,则是调用服务来请求数据的,而服务获得数据可以通过超文本传送协议(超文本传输协议的缩写)服务(AngularJS内置的服务)来请求后端的网络应用编程接口来获得所需要的数据。
AngularJS系统内置的服务以$开头,我们也可以自己定义一个服务。定义服务的方式有如下几种:
使用系统内置的$提供服务使用组件的工厂方法使用组件的服务方法在前面的例子我们都是以工厂方法创建服务的,接下来演示下如何使用$提供服务来创建一个服务,具体的代码如下所示:
!DOCTYPE html html ng-app=' mainApp ' xmlns=' http://www。w3。org/1999/XHTML ' head meta http-equiv=' Content-Type ' Content=' text/html;charset=utf-8 '/title anglarjs指令演示/title脚本src=' http :http://沙箱。运行js。cn/uploads/RS/376/pbcx3e 1z/jquery-1。10 .2 .量滴js /脚本脚本src=' http :http://沙箱。运行js。cn/uploads/RS/376/pbcx3e 1z/angular。量滴js /脚本脚本(function(){ var mainApp=angular。模块(' mainApp ',[]).config(['$provide ',function($provide){ //使用系统内置的$提供服务来创建一个提供数据的服务器$provide.factory('service ',function () { var list=[ { id: 1,title: '博客园,网址: ' http://www。cn博客。com ' },{ id: 2,title: '知乎,url: 'http://www.zhihu.com' },{ id: 3,title: 'codeproject ',url: 'http://www。代码项目。com/' },{ id: 4,title: 'stackoverflow ',URL : ' http://www。堆栈溢出。com/' };返回函数(id) { //假如身份为无效值返回所有if(!id)返回列表;var t=0;//匹配返回的项目angular.forEach(list,function (v,I){ if(v . id==id)t=I;});返回列表[t];};});}]);mainApp.directive('imCheck ',[function(){ return { restrict : ' A ',replace: false,link: function(作用域,元素){ var all=' and input[type=' checkbox ']';var item=' t body input[type=' checkbox ']';//当点击选择所有项目element.on('change ',all),function () { var o=$(this).道具('选中');var TDS=元素。find(item);tds .每个(函数(我,支票){ $(支票)).道具('已检查,o);});});//子项修改时的超值element.on('change ',item,function () { var o=$(this).道具('选中');var Ischecked=true if(o){ element . find(item).每个(函数(){ if(!$(这个)。prop(' checked '){ isChecked=false;返回false}返回true });} element.find(all).道具('选中,o isChecked);});} };}]);mainapp。控制器(' dectController ',['$scope ',' service ',函数($scope,service){ $ scope。list=service();}]);})()/脚本/头体h2AngularJs指令演示/h2表ng-控制器=' dect控制器' im-检查输入类型='复选框'选择/th网站第/次网站名称/th链接地址/th/tr/TD t车身tr ng-repeat='列表中的项目t输入类型=' checkbox '/TD TD { { item }。id } }/TD { { item }。title } }/TD { { item。网址} }/TD/tr/t正文/表格/正文/html 3.7过滤器
AngularJs过滤器就是用来格式化数据的,包括排序,筛选、转化数据等操作。下面代码创建了一个反转过滤器。
!DOCTYPE html html ng-app=' mainApp ' xmlns=' http://www . w3 . org/1999/XHTML ' head meta http-equiv=' Content-Type ' Content=' text/html;charset=utf-8 '/title anglarjs筛选器演示/title script src=' http :http://sandbox.runjs.cn/uploads/RS/376/pbcx3e1z/angular.min.js'/脚本脚本(function(){ var mainApp=angular . module(' mainApp ',[]);//定义反转过滤器,用于格式化数据(转换、排序、过滤等)。).mainApp.filter('reverse ',function(){ return function(input,大写){ input=input | |var out=for(var I=0;输入长度;I){ out=input . charat(I)out;} if(大写){ out=out . touppercase();}返回;};});mainapp . controller(' filter controller ',['$scope ',function($ scope){ $ scope . helling=' AngularJs ';}]);})()/script/head body div ng-controller=' filter controller ' input ng-model=' helling ' type=' text ' Br No filter : { { helling } } Br reverse 3360 { { helling | reverse } } Br reverse大写: { { helling | reverse : true } } Br/div/body/html 3.8前端模块化开发
前面例子中的实现并不是我们在实际开发中推荐的方式,因为前面例子中所有的前端逻辑都放在一个Html文件中,不利于后期的维护。一旦业务逻辑变得复杂,这个Html文件就会变得复杂,这使得跟踪问题和修复bug变得更加困难。在后端开发的过程中,我们经常会谈到单一责任,把功能类似的代码放在一起。前端开发也可以这样做。对应的模块化框架有:RequireJs、SeaJs等。
您还可以使用AngularJs内置的模块化来更好地组织代码结构。请下载本文末尾的具体代码。下面是模块化开发的截图:
四.摘要
至此,本文的所有内容都结束了。在后面的文章中,我将分享一个使用AngularJs的简单权限管理系统的实现。以上就是本文的全部内容。希望对大家的学习有帮助,支持我们。