angularjs详解
1 前言
前端技术的发展是如此之快,各种优秀技术、优秀框架的出现简直让人目不暇接,紧跟时代潮流,学习掌握新知识自然是不敢怠慢。
AngularJS是google在维护,其在国外已经十分火热,可是国内的使用情况却有不小的差距,参考文献/网络文章也很匮乏。这里便将我学习AngularJS写成文档,一方面作为自己学习路程上的记录,另一方面也给有兴趣的同学一些参考。
首先我自己也是一名学习者,会以学习者的角度来整理我的行文思路,这里可能只是些探索,有理解或是技术上的错误还请大家指出;其次我特别喜欢编写小例子来把一件事情说明白,故在文中会尽可能多的用示例加代码讲解,我相信这会是一种比较好的方式;最后,我深知AngularJS的使用方式跟jquery的使用方式有很大不同,在大家都有jquery、ext经验的条件下对于angular的学习会困难重重,不过我更相信在大家的坚持下,能够快速的学好AngularJS,至少咱也能深入了解到AngularJS的基本思想,对咱们以后自己的插件开发、项目开发都会有很大的启示。
2 AngularJS概述
2.1 AngularJS是什么?
为了实现这些,ng引入了一些非常棒的特性,包括模板机制、数据绑定、模块、指令、依赖注入、路由。通过数据与模板的绑定,能够让我们摆脱繁琐的DOM操作,而将注意力集中在业务逻辑上。
2.2 AngularJS简单介绍
AngularJS 重新定义了前端应用的开发方式。面对HTML和JavaScript之间的界线,它
API地址:http://docs.angularjs.org/api/;
AngularJS在github上的中文粗译版地址:https://github.com/basestyle/angularjs-cn。
2.3 什么时候该用AngularJS
3 AugularJS特性
3.1 特性一:双向的数据绑定
我们想象一下Model是你的应用中的简单事实。你的Model是你用来读取或者更新的部分。数据绑定指令提供了你的Model投射到view的方法。这些投射可以无缝的,毫不影响的应用到web应用中。
这些互动,然后融合到一个model中,并且更新View。这是一个手动的复杂过程,当一个应用非常庞大的时候,将会是一件非常费劲的事情。
这里肯定有更好的解决方案!那就是AngularJS的双向数据绑定,能够同步DOM和Model等等。
这里有一个非常简单的例子,用来演示一个input输入框和<h1>元素的双向绑定(例01):
<script src="./js/angular.min.js"></script>
<input type="text" ng-model="user.name" placeholder="请输入名字">
<h1>Hello, {{user.name}}!</h1>
说明:实际效果请大家看AngularJS/demo/index.html
3.2 特性二:模板
在AngularJS中,一个模板就是一个HTML文件。但是HTML的内容扩展了,包含了很多帮助你映射model到view的内容。
最大的好处是为设计师和开发者创建了一个紧密的工作流。设计师可以像往常一样开发标签,然后开发者拿过来添加上功能,通过数据绑定将会使得这个过程非常简单。
这里有一个例子,我们使用ng-repeat指令来循环图片数组并且加入img模板,如下:
{"image":"img/image_01.png", "description":"Image 01 description"},
{"image":"img/image_02.png", "description":"Image 02 description"},
{"image":"img/image_03.png", "description":"Image 03 description"},
{"image":"img/image_04.png", "description":"Image 04 description"},
{"image":"img/image_05.png", "description":"Image 05 description"}
<div ng-controller="AlbumCtrl">
<li ng-repeat="image in images">
<img ng-src="{{image.thumbnail}}" alt="{{image.description}}">
这里还有一件事值得提一句,AngularJS并不强制你学习一个新的语法或者从你的应用中提出你的模板。
3.3 特性三:MVC
viewmodel是一个用来提供特别数据和方法从而维护指定view的对象。
viewmodel是$scope的对象,只存在于AnguarJS的应用中。$scope只是一个简单的js对象,这个对象使用简单的API来侦测和广播状态变化。
controller负责设置初始状态和参数化$scope方法用以控制行为。需要指出的controller并不保存状态也不和远程服务互动。
view是AngularJS解析后渲染和绑定后生成的HTML 。这个部分帮助你创建web应用的架构。$scope拥有一个针对数据的参考,controller定义行为,view处理布局和互动。
3.4 特性四:服务和依赖注入
AngularJS拥有内建的依赖注入(DI)子系统,可以帮助开发人员更容易的开发,理解和测试应用。
DI允许你请求你的依赖,而不是自己找寻它们。比如,我们需要一个东西,DI负责找创建并且提供给我们。
为了而得到核心的AngularJS服务,只需要添加一个简单服务作为参数,AngularJS会侦测并且提供给你:
function EditCtrl($scope, $location, $routeParams) {
angular.module('MyServiceModule', []).
factory('notify', ['$window', function (win) {
function myController(scope, notifyService) {
scope.callNotify = function (msg) {
myController.$inject = ['$scope', 'notify'];
3.5 特性五:指令(Directives)
指令是我个人最喜欢的特性。你是不是也希望浏览器可以做点儿有意思的事情?那么AngularJS可以做到。
指令可以用来创建自定义的标签。它们可以用来装饰元素或者操作DOM属性。可以作为标签、属性、注释和类名使用。
这里是一个例子,它监听一个事件并且针对的更新它的$scope ,如下:
myModule.directive('myComponent', function(mySharedService) {
controller: function($scope, $attrs, mySharedService) {
$scope.$on('handleBroadcast', function() {
$scope.message = 'Directive: ' + mySharedService.message;
<my-component ng-model="message"></my-component>
使用一系列的组件来创建你自己的应用将会让你更方便的添加,删除和更新功能。
4 功能介绍
4.1数据绑定
从View到Controller再到View的数据交互(例01):
<input type="text" ng-model="user.name" placeholder="请输入名称"/>
关键: ng-app 、 ng-model 和 { {user.name } }
首先: <html>元素的ng-app属性。标识这个DOM里面的内容将启用AngularJS应用。
其次:告诉AngularJS,对页面上的“user.name” 这个Model进行双向数据绑定。
第三:告诉AngularJS,在“{{ user.name}}”这个指令模版上显示“user.name”这个Model的数据。
从Server到Controller再到View的数据交互(例02):
<div ng-controller="demoController">
<input type="text" ng-model="user.name" disabled="disabled"/>
<a href="javascript:void(0);" ng-click="getAjaxUser()">AJAX获取名字</a>
demoApp.controller("demoController", function($http, $scope){
$scope. getAjaxUser = function(){
// $http.get({url:"../xxx.action"}).success(function(data){
$scope.user = {"name":"从JOSN中获取的名称","age":22};
4.2 scopes、module、controller
4.2.1 scopes
每一个Angular应用都会有一个 $rootScope。这个 $rootScope 是最顶级的scope,它对应着含有 ng-app 指令属性的那个DOM元素。
app.run(function($rootScope) { $rootScope.name = "张三"; });
如果页面上没有明确设定 $scope ,Angular 就会把数据和函数都绑定到这里, 第一部分中的例子就是靠这一点成功运行的。
这样,我们就可以在view的任何地方访问这个name属性,使用模版表达式{{}},像这样:
4.2.2 module
在ng中,模板十分简单,它就是我们页面上的HTML代码,不需要附加任何额外的东西。在模板中可以使用各种指令来增强它的功能,这些指令可以让你把模板和数据巧妙的绑定起来。
var demoApp = angular.module('demoApp', []);
4.2.3 ng-controller
要明确创建一个$scope 对象,我们就要给DOM元素安上一个controller对象,使用的是ng-controller 指令属性:
<div ng-controller="MyController"> {{ person.name }} </div>
唯一的例外:有些指令属性可以选择性地创建一个独立的scope,让这个scope不继承它的父scope们,这个会在指令详解中说明。
4.3 ajax
$http 服务是AngularJS的核心服务之一,它帮助我们通过XMLHttpRequest对象或JSONP与远程HTTP服务进行交流。
demoApp.controller("demoController", function($http, $scope){
$scope. getAjaxUser = function(){
$http.get({url:"../xxx.action"}).success(function(data){
AngularJS的AJAX与jquery等框架的AJAX基本一致,这里就不多说了。
4.4表达式
我们在使用其他模板库时,一般都会有模板的循环输出、分支输出、逻辑判断等类似的控制。
要想理解指令属性的运作,我们必须先理解表达式。在之前的例子里我们已经见过表达式,例如 {{ user.name }}。
{{ person }} {"name":"Ari Lerner"}
{{ 10 * 3.3 | currency }} $33.00
表达式粗略来看有点像 eval(javascript) 的结果。它们会经过Angular.js的处理,从而拥有以下重要而独特的性质:
l 所有表达式都在scope这个context里被执行,因此可以使用所有本地 $scope 中的变量。
l 如果一个表达式的执行导致类型错误或引用错误,这些错误将不会被抛出。
l 表达式里不允许任何控制函数流程的功能(如if/else等条件语句)
4.5过滤器
4.5.1过滤器使用方式
总共九种。除此之外还可以自定义过滤器,这个就强大了,可以满足任何要求的数据处理。Filter还是很简单的,需要明白的是内置的filter如何使用,以及自己如何定义一个filter。
我们可以直接在{{}}中使用filter,跟在表达式后面用 | 分割,语法如下:
也可以多个filter连用,上一个filter的输出将作为下一个filter的输入:
{{ expression | filter1 | filter2 | ... }}
{{ expression | filter:argument1:argument2:... }}
除了对{{}}中的数据进行格式化,我们还可以在指令中使用filter,例如先对数组array进行过滤处理,然后再循环输出:
<span ng-repeat="a in array | filter ">
2. 在controller和service中使用filter
我们的js代码中也可以使用过滤器,方式就是我们熟悉的依赖注入,例如我要在controller中使用currency过滤器,只需将它注入到该controller中即可,代码如下:
app.controller('testC',function($scope,currencyFilter){
$scope.num = currencyFilter(123534);
在模板中使用{{num}}就可以直接输出$123,534.00了!在服务中使用filter也是同样的道理。
如果你要在controller中使用多个filter,并不需要一个一个注入吗,ng提供了一个$filter服务可以来调用所需的filter,你只需注入一个$filter就够了,使用方法如下:
app.controller('testC',function($scope,$filter){
$scope.num = $filter('currency')(123534);
$scope.date = $filter('date')(new Date());
可以达到同样的效果。好处是你可以方便使用不同的filter了。
4.5.2 ng的内置过滤器
ng内置了九种过滤器,使用方法都非常简单,看文档即懂。不过为了以后不去翻它的文档,我在这里还是做一个详细的记录。
1. currency (货币处理)
使用currency可以将数字格式化为货币,默认是美元符号,你可以自己传入所需的符号,例如我传入人民币:
{{num | currency : '¥'}}
2. date (日期格式化)
原生的js对日期的格式化能力有限,ng提供的date过滤器基本可以满足一般的格式化要求。用法如下:
{{date | date : 'yyyy-MM-dd hh:mm:ss EEEE'}}
参数用来指定所要的格式,y M d h m s E 分别表示 年 月 日 时 分 秒 星期,你可以自由组合它们。也可以使用不同的个数来限制格式化的位数。另外参数也可以使用特定的描述性字符串,例如“shortTime”将会把时间格式为12:05 pm这样的。ng提供了八种描述性的字符串,个人觉得这些有点多余,我完全可以根据自己的意愿组合出想要的格式,不愿意去记这么多单词~
3. filter(匹配子串)
这个名叫filter的filter。用来处理一个数组,然后可以过滤出含有某个子串的元素,作为一个子数组来返回。可以是字符串数组,也可以是对象数组。如果是对象数组,可以匹配属性的值。它接收一个参数,用来定义子串的匹配规则。下面举个例子说明一下参数的用法,我用现在特别火的几个孩子定义了一个数组:
$scope.childrenArray = [
{name:'kimi',age:3},
{name:'cindy',age:4},
{name:'anglar',age:4},
{name:'shitou',age:6},
{name:'tiantian',age:5}
];
$scope.func = function(e){return e.age>4;}{{ childrenArray | filter : 'a' }} //匹配属性值中含有a的
{{ childrenArray | filter : 4 }} //匹配属性值中含有4的
{{ childrenArray | filter : {name : 'i'} }} //参数是对象,匹配name属性中含有i的
{{childrenArray | filter : func }} //参数是函数,指定返回age>4的
4. json(格式化json对象)
json过滤器可以把一个js对象格式化为json字符串,没有参数。这东西有什么用呢,我一般也不会在页面上输出一个json串啊,官网说它可以用来进行调试,嗯,是个不错的选择。或者,也可以用在js中使用,作用就和我们熟悉的JSON.stringify()一样。用法超级简单:
{{ jsonTest | json}}
5. limitTo(限制数组长度或字符串长度)
limitTo过滤器用来截取数组或字符串,接收一个参数用来指定截取的长度,如果参数是负值,则从数组尾部开始截取。个人觉得这个filter有点鸡肋,首先只能从数组或字符串的开头/尾部进行截取,其次,js原生的函数就可以代替它了,看看怎么用吧:
{{ childrenArray | limitTo : 2 }} //将会显示数组中的前两项
6. lowercase(小写)
把数据转化为全部小写。太简单了,不多解释。同样是很鸡肋的一个filter,没有参数,只能把整个字符串变为小写,不能指定字母。怎么用我都懒得写了。
7. uppercase(大写)
同上。
8. number(格式化数字)
number过滤器可以为一个数字加上千位分割,像这样,123,456,789。同时接收一个参数,可以指定float类型保留几位小数:
{{ num | number : 2 }}
9. orderBy(排序)
orderBy过滤器可以将一个数组中的元素进行排序,接收一个参数来指定排序规则,参数可以是一个字符串,表示以该属性名称进行排序。可以是一个函数,定义排序属性。还可以是一个数组,表示依次按数组中的属性值进行排序(若按第一项比较的值相等,再按第二项比较),还是拿上面的孩子数组举例:
<div>{{ childrenArray | orderBy : 'age' }}</div> //按age属性值进行排序,若是-age,则倒序
<div>{{ childrenArray | orderBy : orderFunc }}</div> //按照函数的返回值进行排序
<div>{{ childrenArray | orderBy : ['age','name'] }}</div> //如果age相同,按照name进行排序 内置的过滤器介绍完了,写的我都快睡着了。。。正如你所看到的,ng内置的过滤器也并不是万能的,事实上好多都比较鸡肋。更个性化的需求就需要我们来定义自己的过滤器了,下面来看看如何自定义过滤器。
4.5.3自定义过滤器及示例
filter的自定义方式也很简单,使用module的filter方法,返回一个函数,该函数接收
输入值,并返回处理后的结果。话不多说,我们来写一个看看。比如我需要一个过滤器,它可以返回一个数组中下标为奇数的元素,代码如下:
app.filter('odditems',function(){
for(var i=0;i<inputArray.length;i++){
格式就是这样,你的处理逻辑就写在内部的那个闭包函数中。你也可以让自己的过滤器接收参数,参数就定义在return的那个函数中,作为第二个参数,或者更多个参数也可以。
First name:<input ng-model="user.firstName"/><br/>
Last name:<input ng-model="user.lastName"/> <br/>
First name:{{user.firstName}} Last name:{{user.lastName}} <br/>
Fullname:{{user | flFullname}}<br/>
Fullname:{{user | flFullname:"-"}}<br/>
Fullname:{{user | flFullname:"•" | uppercase }}
demoApp.filter("flFullname", function() {
if(user.firstName){fullName += user.firstName;}
if(user.lastName){fullName = fullName + sep + user.lastName;}
if(fullName && fullName.length>0){return fullName;
4.6指令(directive)
通过使用模板,我们可以把model和controller中的数据组装起来呈现给浏览器,还可以通过数据绑定,实时更新视图,让我们的页面变成动态的。
1.指令(directive):ng提供的或者自定义的标签和属性,用来增强HTML表现力;
2.标记(markup):即双大括号{{}},可将数据单向绑定到HTML中;
其中,指令无疑是使用量最大的,ng内置了很多指令用来控制模板,如ng-repeat,ng-class,也有很多指令来帮你完成业务逻辑,如ng-controller,ng-model。
l 作为属性:<span my-dir="exp"></span>
l 作为注释:<!-- directive: my-dir exp -->
l 作为类名:<span class="my-dir: exp;"></span>
4.6.1样式相关的指令
既然模板就是普通的HTML,那我首要关心的就是样式的控制,元素的定位、字体、背景色等等如何可以灵活控制。下面来看看常用的样式控制指令。
ng-class用来给元素绑定类名,其表达式的返回值可以是以下三种:
l 类名字符串,可以用空格分割多个类名,如’redtext boldtext’;
l 一个名值对应的map,其键值为类名,值为boolean类型,当值为true时,该类会被加在元素上。
map:{redtext:{{red}}, boldtext:{{bold}}, striketext:{{strike}}}
<div class=”{{style}}text”>字体样式测试</div>
注意我用了class而不是ng-class,这是不可以对换的,官方的文档也未做说明,姑且认为这是ng的语法规则吧。
ng-style用来绑定元素的css样式,其表达式的返回值为一个js对象,键为css样式名,值为该样式对应的合法取值。用法比较简单:
<div ng-style="{color:'red'}">ng-style测试</div>
<div ng-style="style">ng-style测试</div>
4.6.2表单控件功能相关指令
ng-checked控制radio和checkbox的选中状态
4.6.3事件绑定相关指令
事件绑定是javascrpt中比较重要的一部分内容,ng对此也做了详细的封装,正如我们之前使用过的ng-click一样,事件的指令如下:
<select ng-change=”change($event)”></select>
$scope.change = function($event){
在模板中可以用变量$event将事件对象传递到controller中。
4.6.4特殊的ng-src和ng-href
在说明这两个指令的特殊之前,需要先了解一下ng的启动及执行过程,如下图:
3) angular监听DOMContentLoaded 事件,监听到时开始启动;
5) 找到app中定义的Module使用$injector服务进行依赖注入;
6) 根据$injector服务创建$compile服务用于编译;
可以看到,ng框架是在DOMcontent加载完毕后才开始发挥作用。假如我们模板中有一张图片如下:
那么在页面开始加载到ng编译完成之前,页面上会一直显示一张错误的图片,因为路径{{imgUrl}}还未被替换。
为了避免这种情况,我们使用ng-src指令,这样在路径被正确得到之前就不会显示找不到图片。同理,<a>标签的href属性也需要换成ng-href,这样页面上就不会先出现一个地址错误的链接。
候出这个问题,只需在index.html中的模板中换成ng-bind就行。其他的模板是我们动态加载的,就可以放心使用{{}}了。
4.6.5 自定义指令示例
demoApp.directive('userInfo',function(){
templateUrl : 'userInfoTemplate.html',
link : function(scope,element,attrs){
scope.toggleText = function(){
scope.showText = ! scope.showText;
<script type="text/ng-template" id="userInfoTemplate.html">
<div class="mytitle" style="cursor: pointer;" ng-click="toggleText()">
<div ng-transclude ng-show="showText">
将当前元素的内容添加到有ng-transclude属性的这个DIV下,默认是隐藏的。
demoApp.controller("test7Controller", function($scope){
$scope.text = '大家好,我正在研究AngularJs,欢迎大家与我交流。';
$scope.updateInfo = function (){
<user-info etitle="title">{ {text} }</user-info>
Etitle指向Controller中的$scope.title。注意命名方式:指令名为userInfo,对应的标签为user-info。
4.7服务(service)
4.7.1服务介绍
服务这个概念其实并不陌生,在其他语言中如java便有这样的概念,其作用就是对外提供某个特定的功能,如消息服务,文件压缩服务等,是一个独立的模块。ng的服务是这样定义的:
首先是一个单例,即无论这个服务被注入到任何地方,对象始终只有一个实例。
其次这与我们自己定义一个function然后在其他地方调用不同,因为服务被定义在一个模块中,所以其使用范围是可以被我们管理的。ng的避免全局变量污染意识非常强。
ng提供了很多内置的服务,可以到API中查看http://docs.angularjs.org/api/。知道了概念,我们来拉一个service出来溜溜,看看到底是个什么用法。
我们在controller中直接声明$location服务,这依靠ng的依赖注入机制。$location提供地址栏相关的服务,我们在此只是简单的获取当前的地址。
服务的使用是如此简单,我们可以把服务注入到controller、指令或者是其他服务中。
4.7.2自定义服务
如同指令一样,系统内置的服务以$开头,我们也可以自己定义一个服务。定义服务的方式有如下几种:
下面通过一个小例子来分别试验一下。我们定义一个名为remoteData服务,它可以从远程获取数据,这也是我们在程序中经常使用的功能。不过我这里没有远程服务器,就写死一点数据模拟一下。
var app = angular.module('MyApp', [], function($provide) {
$provide.factory('remoteData', function() {
var data = {name:'n',value:'v'};
app.factory('remoteData',function(){
var data = {name:'n',value:'v'};
app.service('remoteData',function(){
Module的factory和$provide的factory方法是一模一样的,从官网文档看它们其实就是一回事。至于Module内部是如何调用的,我此处并不打算深究,我只要知道怎么用就好了。
4.7.3管理服务的依赖关系
服务与服务中间可以有依赖关系,例如我们这里定义一个名为validate的服务,它的作用是验证数据是否合法,它需要依赖我们从远程获取数据的服务remoteData。代码如下:
app.factory('validate',['remoteData',function(remoteDataService){
if(remoteDataService.name=='n'){
我们在controller中注入服务也是同样的道理,使用的名称需要与服务名称一致才可以正确注入。否则,你必须使用$inject来手动指定注入的服务。比如:
alert('name:'+rd.name+' value:'+rd.value);
testC.$inject = ['$scope','remoteData'];
在controller中注入服务,也可以在定义controller时使用数组作为第二个参数,在此处
把服务注入进去,这样在函数体中使用不一致的服务名称也是可以的,不过要确保注入的顺序是一致的,如:
app.controller('testC',['$scope','remoteData',function($scope,rd){
alert('name:'+rd.name+' value:'+rd.value);
4.7.4 自定义服务示例
接下来让我们看下例子(例08 自定义服务)代码,自定义userService服务:
demoApp.factory('userService', ['$http', function($http) {
var doGetUser = function(userId, path) {
var data = {userId:"woshishui",userName:"我是谁",userInfo:"我是谁!我是谁!"};;
data = {userId:"zhangsan",userName:"张三",userInfo:"我是张三,我为自己"};
data = {userId:"lisi",userName:"李四",userInfo:"我是李四,我为卿狂!"};
return doGetUser(userId, '../xxx/xxx.action');
我们创建了一个只有一个方法的userService,getUser为这个服务从后台获取用户信息的函数,并且对外暴露。当然,由于这是一个静态的例子,无法访问后台,那么我们便制定其返回的数据。
demoApp.controller("test8Controller", function($scope,userService){
$scope.showUserInfo = false;//显示作者详细信息开关
$scope.currentUser = {}; //当前选中的作者
$scope.getUserInfo = function(userId){
$scope.currentUser = userService.getUser(userId);
setTimeout(function(){//定时器:隐藏作者详细信息
我们的userService注入到我们的test8Controller后,我们就可以像使用其他服务(我们前面提到的$http服务)一样的使用userService了。
<tr ng-repeat="article_ in articles">
<a href="javascript:void(0);" ng-click="getUserInfo(article_.userId)"> {{article_.userName}} </a>
用户ID:{{currentUser.userId}}<br/>
用户名:{{currentUser.userName}}<br/>
用户简介:{{currentUser.userInfo}}<br/>
4.8依赖注入DI
通过依赖注入,ng想要推崇一种声明式的开发方式,即当我们需要使用某一模块或服务时,不需要关心此模块内部如何实现,只需声明一下就可以使用了。在多处使用只需进行多次声明,大大提高可复用性。
比如我们的controller,在定义的时候用到一个$scope参数。
app.controller('testC',function($scope){});
如果我们在此处还需操作其他的东西,比如与浏览器地址栏进行交互。我们只需再多添
app.controller('testC',function($scope,$location){});
这便是依赖注入机制。顺理成章的推断,我们可以自己定义模块和服务,然后在需要的地方进行声明,由框架来替我们注入。
app.factory('tpls',function(){
return ['tpl1','tpl2','tpl3','tpl4'];
app.controller('testC',function($scope,tpls){
$scope.question = questionModel;
$scope.nowTime = new Date().valueOf();
$scope.templates = tpls; //赋值到$scope中
$scope.addOption = function(){
$scope.question.options.push(o);
$scope.delOption = function(index){
$scope.question.options.splice(index,1);
此时,若在模板中书写如下代码,我们便可以获取到服务tpls所提供的数据了:
<a href="javascript:void(0);" ng-repeat="t in templates">{{t}} </a><br />
4.9路由(route)
如此一来,便形成了通过地址栏进行导航的深度链接(deeplinking ),也就是我们所需要的路由机制。通过路由机制,一个单页应用的各个视图就可以很好的组织起来了。
4.9.1 ngRoute内容
l 服务$routeProvider用来定义一个路由表,即地址栏与视图模板的映射
l 服务$routeParams保存了地址栏中的参数,例如{id : 1, name : 'tom'}
l 服务$route完成路由匹配,并且提供路由相关的属性访问及事件,如访问当前路由对应的controller
以上内容再加上$location服务,我们就可以实现一个单页面应用了。下面来看一下具体如何使用这些内容。
4.9.2 ng的路由机制
ngRoute模块包含在一个单独的文件中,所以第一步需要在页面上引入这个文件,如下:
<script src="http://code.angularjs.org/1.2.8/angular.min.js"></script>
<script src="http://code.angularjs.org/1.2.8/angular-route.min.js"></script>
光引入还不够,我们还需在模块声明中注入对ngRoute的依赖,如下:
var app = angular.module('MyApp', ['ngRoute']);
完成了这些,我们就可以在模板或是controller中使用上面的服务和指令了。下面我们需要定义一个路由表。
$routeProvider提供了定义路由表的服务,它有两个核心方法,when(path,route)和otherwise(params),先看一下核心中的核心when(path,route)方法。
route参数是一个object,用来指定当path匹配后所需的一系列配置项,包括以下内容:
l controller //function或string类型。在当前模板上执行的controller函数,生成新的scope;
l controllerAs //string类型,为controller指定别名;
l template //string或function类型,视图z所用的模板,这部分内容将被ngView引用;
l templateUrl //string或function类型,当视图模板为单独的html文件或是使用了<script type="text/ng-template">定义模板时使用;
l resolve //指定当前controller所依赖的其他模块;
最简单情况,我们定义一个html文件为模板,并初始化一个指定的controller:
function emailRouteConfig($routeProvider){
$routeProvider.when('/show', {
otherwise(params)方法对应路径匹配不到时的情况,这时候我们可以配置一个redirectTo参数,让它重定向到404页面或者是首页。
我们的单页面程序都是局部刷新的,那这个“局部”是哪里呢,这就轮到ngView出马了,只需在模板中简单的使用此指令,在哪里用,哪里就是“局部”。例如:
<div ng-view></div> 或:<ng-view></ng-view>
我们的子视图将会在此处被引入进来。完成这三步后,你的程序的路由就配置好了。
4.9.3 路由示例
demoApp.config(['$routeProvider',function($routeProvider) {
$routeProvider.when('/list', {
templateUrl: 'route/list.html',
controller: 'routeListController'
templateUrl: 'route/detail.html',
controller: 'routeDetailController'
/list 对应为:route/list.html页面,显示用户列表;/list/:id对应于route/detail.html页面,显示用户详细信息。
2.为list.html和detail.html分别声明Controller:routeListController和routeDetailController。
demoApp.controller('routeListController',function($scope) {
$scope.users = [{userId:"zhangsan",userName:"张三",userInfo:"我是张三,我为自己带盐!"},
{userId:"lisi",userName:"李四",userInfo:"我是李四,我为卿狂!"},
{userId:"woshishui",userName:"我是谁",userInfo:"我是谁!我是谁!我是谁!"}];
demoApp.controller('routeDetailController',function($scope, $routeParams, userService) {
$scope.userDetail = userService.getUser($routeParams.id);
routeDetailController中如上面提到的一样,注入了userService服务,在这里直接拿来用。
3.创建list.html和detail.html页面,代码如下:
<h3>Route : List.html(用户列表页面)</h3>
<li ng-repeat="user in users">
<a href="#/list/{{ user.userId }}"> {{ user.userName }}</a>
<h3>Route : detail.html(用户详细信息页面)</h3>
<h3>用户名:<span style="color: red;">{{userDetail.userName}}</span></h3>
<span>用户ID:{{userDetail.userId}}</span><span>用户名:{{userDetail.userName}}</span>
用户简介:<span>{{userDetail.userInfo}}</span>
<h1>AngularJS路由(Route) 示例</h1>
4.10 NG动画效果
4.10.1 NG动画效果简介
NG动画效果,现在可以通过CSS3或者是JS来实现,如果是通过JS来实现的话,需要其他JS库(比如JQuery)来支持,实际上底层实现还是靠其他JS库,只是NG将其封装了,
- enter:元素添加到DOM中时执行动画;
- leave:元素从DOM删除时执行动画;
- move:移动元素时执行动画;
- beforeAddClass:在给元素添加CLASS之前执行动画;
- addClass:在给元素添加CLASS时执行动画;
- beforeRemoveClass:在给元素删除CLASS之前执行动画;
- removeClass:在给元素删除CLASS时执行动画。
var ngModule = angular.module('YourApp', ['ngAnimate']);
demoApp.animation('.my-crazy-animation', function() {
enter: function(element, done) {
//run the animation here and call done when the animation is complete
//this (optional) function will be called when the animation
//completes or when the animation is cancelled (the cancelled
//flag will be set to true if cancelled).
leave: function(element, done) { },
move: function(element, done) { },
//animation that can be triggered before the class is added
beforeAddClass: function(element, className, done) { },
//animation that can be triggered after the class is added
addClass: function(element, className, done) { },
//animation that can be triggered before the class is removed
beforeRemoveClass: function(element, className, done) { },
//animation that can be triggered after the class is removed
removeClass: function(element, className, done) { }
4.10.2 动画效果示例
1.首先,我们在demoApp下定义一个动画效果,匹配CLASS:” .border-animation”
demoApp.animation('.border-animation', function(){
beforeAddClass : function (element, className, done) {
removeClass : function (element ,className ,done ) {
动画效果的含义就是:在匹配CLASS为border-animation的元素添加一个CLASS之前使其边框的宽度在2秒内变为1PX;并在其移除一个CLASS时使其边框的宽度在3秒内变为50PX。
2. 视图中的代码如下(主要,其他相关样式请查看例子代码):
<div class="border-animation" ng-show="testShow"></div>
<a href="javascript:void(0);" ng-click="testShow=!testShow" >Change</a>
ng-show为false时会为其加上“ng-hide“的CLASS; ng-show为true时会为其移除“ng-hide“的CLASS,从而触发动画效果。
demoApp.controller("test10Controller", function($scope, $animate){
5 功能演示
6 AngularJS进阶
6.1数据绑定原理研究
6.1.1 AngularJS扩展事件循环
6.1.2 $watch 队列
每次你绑定一些东西到你的DOM上时你就会往$watch队列里插入一条$watch。想象一下$watch就是那个可以检测它监视的model里时候有变化的东西。例如你有如下的代码:
User: <input type="text" ng-model="user" />
Password: <input type="password" ng-model="pass" />
在这里我们有个$scope.user,他被绑定在了第一个输入框上,还有个$scope.pass,它被绑定在了第二个输入框上,然后我们在$watch list里面加入两个$watch。
/*Controller controllers.js */
app.controller('MainCtrl', function($scope) {
这里,即便我们在$scope上添加了两个东西,但是只有一个绑定在了DOM上,因此在这里只生成了一个$watch。
/*Controller controllers.js */
app.controller('MainCtrl', function($scope) {
<li ng-repeat="person in people">
{{person.name}} - {{person.age}}
这里又生成了多少个$watch呢?每个person有两个(一个name,一个age),然后ng-repeat又有一个,因此10个person一共是(2 * 10) +1,也就是说有21个$watch。
因此,每一个绑定到了DOM上的数据都会生成一个$watch。
当我们的模版加载完毕时,也就是在linking阶段(Angular分为compile阶段和linking阶段),Angular解释器会寻找每个directive,然后生成每个需要的$watch。
6.1.3 $digest循环
/*Controller controllers.js */
app.controller('MainCtrl', function() {
$scope.changeFoo = function() {
<button ng-click="changeFoo()">Change the name</button>
这里我们有一个$watch因为ng-click不生成$watch(函数是不会变的)。
•浏览器接收到一个事件,进入angular context;
•$digest循环开始执行,查询每个$watch是否变化;
•由于监视$scope.name的$watch报告了变化,它会强制再执行一次$digest循环;
•浏览器拿回控制权,更新与$scope.name新值相应部分的DOM。
这里很重要的是每一个进入angular context的事件都会执行一个$digest循环,也就是说每次我们输入一个字母循环都会检查整个页面的所有$watch。
6.1.4如何进入angular context
谁决定什么事件进入angular context,而哪些又不进入呢?通过$apply!
这是Angular新手共同的痛处。为什么我的jQuery不会更新我绑定的东西呢?因为jQuery没有调用$apply,事件没有进入angular context,$digest循环永远没有执行。
假设我们有下面这个directive和controller。
app.directive('clickable', function() {
template: '<ul style="<li>{{foo}}</li><li>{{bar}}</li></ul>',
link: function(scope, element, attrs) {
element.bind('click', function() {
app.controller('MainCtrl', function($scope) {
element.bind('click', function() {
element.bind('click', function() {
因此,如果你想使用一个jQuery插件,并且要执行$digest循环来更新你的DOM的话,要确保你调用了$apply。
有时候我想多说一句的是有些人在不得不调用$apply时会“感觉不妙”,因为他们会觉得他们做错了什么。其实不是这样的,Angular不是什么魔术师,他也不知道第三方库想要更新绑定的数据。
6.1.5使用$watch来监视
你已经知道了我们设置的任何绑定都有一个它自己的$watch,当需要时更新DOM,但是我们如果要自定义自己的watches呢?简单,来看个例子:
app.controller('MainCtrl', function($scope) {
$scope.$watch('name', function() {
<body ng-controller="MainCtrl">
Name updated: {{updated}} times.
这就是我们创造一个新的$watch的方法。第一个参数是一个字符串或者函数,在这里是只是一个字符串,就是我们要监视的变量的名字,在这里,$scope.name(注意我们只需要
用name)。第二个参数是当$watch说我监视的表达式发生变化后要执行的。我们要知道的第一件事就是当controller执行到这个$watch时,它会立即执行一次,因此我们设置updated为-1。
app.controller('MainCtrl', function($scope) {
$scope.$watch('name', function(newValue, oldValue) {
if (newValue === oldValue) { return; } // AKA first run
<body ng-controller="MainCtrl">
Name updated: {{updated}} times.
watch的第二个参数接受两个参数,新值和旧值。我们可以用他们来略过第一次的执行。通常你不需要略过第一次执行,但在这个例子里面你是需要的。
app.controller('MainCtrl', function($scope) {
$scope.user = { name: "Fox" };
$scope.$watch('user', function(newValue, oldValue) {
if (newValue === oldValue) { return; }
<body ng-controller="MainCtrl">
<input ng-model="user.name" />
Name updated: {{updated}} times.
我们想要监视$scope.user对象里的任何变化,和以前一样这里只是用一个对象来代替前面的字符串。
app.controller('MainCtrl', function($scope) {
$scope.user = { name: "Fox" };
$scope.$watch('user', function(newValue, oldValue) {
if (newValue === oldValue) { return; }
<body ng-controller="MainCtrl">
<input ng-model="user.name" />
Name updated: {{updated}} times.
6.1.6 总结
无论如何,随着ECMAScript6的到来,在Angular未来的版本里我们将会有Object.observe那样会极大改善$digest循环的速度。
6.2自定义指令详解
6.2.1指令的编译过程
在开始自定义指令之前,我们有必要了解一下指令在框架中的执行流程:
1.浏览器得到 HTML 字符串内容,解析得到 DOM 结构。
2.ng 引入,把 DOM 结构扔给 $compile 函数处理:
⑤ 执行指令中的 compile 函数(改变 DOM 结构,返回 link 函数);
⑥ 得到的所有 link 函数组成一个列表作为 $compile 函数的返回。
6.2.2指令的使用方式及命名方法
- 作为标签:<my-dir></my-dir>
- 作为属性:<span my-dir="exp"></span>
- 作为注释:<!-- directive: my-dir exp -->
- 作为类名:<span class="my-dir: exp;"></span>
其实常用的就是作为标签和属性,下面两种用法目前还没见过,感觉就是用来卖萌的,姑且留个印象。我们自定义的指令就是要支持这样的用法。
6.2.3自定义指令的配置参数
myModule.directive('namespaceDirectiveName', function factory(injectables) {
var directiveDefinitionObject = {
restrict: string,//指令的使用方式,包括标签,属性,类,注释
template: string,//指令使用的模板,用HTML字符串的形式表示
templateUrl: string,//从指定的url地址加载模板
replace: bool,//是否用模板替换当前元素,若为false,则append在当前元素上
transclude: bool,//是否将当前元素的内容转移到模板中
scope: bool or object,//指定指令的作用域
link: function postLink(scope, iElement, iAttrs) {...},//以编程的方式操作DOM,包
compile: function compile(tElement, tAttrs, transclude){
pre: function preLink(scope, iElement, iAttrs, controller){...},
post: function postLink(scope, iElement, iAttrs, controller){...}
return directiveDefinitionObject;
l 指令的表现配置参数:restrict、template、templateUrl、replace、transclude;
l 指令间通信配置参数:controller和require。
6.2.3指令的表现参数restrict等
指令的表现配置参数:restrict、template、templateUrl、replace、transclude。
var app = angular.module('MyApp', [], function(){console.log('here')});
app.directive('sayHello',function(){
然后在页面中,我们就可以使用这个名为sayHello的指令了,它的作用就是输出一个hello单词。像这样使用:
稍稍解释一下我们用到的两个参数,restirct用来指定指令的使用类型,其取值及含义如下:
取值 |
含义 |
使用示例 |
E |
标签 |
<my-menu title=Products></my-menu> |
A |
属性 |
<div my-menu=Products></div> |
C |
类 |
<div class="my-menu":Products></div> |
M |
注释 |
<!--directive:my-menu Products--> |
默认值是A。也可以使用这些值的组合,如EA,EC等等。我们这里指定为E,那么它就可以像标签一样使用了。如果指定为A,我们使用起来应该像这样:
replace的作用正如其名,将指令标签替换为了temple中定义的内容。不写的话默认为false。
templateUrl : ‘helloTemplate.html’
<script type="text/ng-template" id="helloTemplate.html">
你可以把这段代码写在页面头部,这样就不必去请求它了。在实际项目中,你也可以将所有的模板内容集中在一个文件中,只加载一次,然后根据id来取用。
接下来我们来看另一个比较有用的配置:transclude,定义是否将当前元素的内容转移到模板中。看解释有点抽象,不过亲手试试就很清楚了,看下面的代码(例06):
app.directive('sayHello',function(){
template : '<div>hello,<b ng-transclude></b>!</div>',
内容是什么你也看到了哈~在运行的时候,美女将会被转移到<b>标签中,原来此配置的作用就是——乾坤大挪移!看效果:
这个还是很有用的,因为你定义的指令不可能老是那么简单,只有一个空标签。当你需要对指令中的内容进行处理时,此参数便大有可用。
6.2.4指令的行为参数:compile和link
不要忘了我们在定义指令中还配置着一个link参数呢,这么多link千万别搞混了。那这
个link函数是干嘛的呢,我们不是有葫芦小金刚了嘛?那我告诉你,其实它是一个小三。此话怎讲?compile函数执行后返回link函数,但若没有配置compile函数呢?葫芦小金刚自然就不存在了。
听完了大总管、葫芦小金刚和小三的故事,你是不是对指令的解析过程比较清晰了呢?不过细细推敲,你可能还是会觉得情节生硬,有些细节似乎还是没有透彻的明白,所以还需要再理解下面的知识点:
尽管compile和link所做的事情差不多,但它们的能力范围还是不一样的。比如正房能管你的存款,小三就不能。小三能给你初恋的感觉,正房却不能。
function compile(tElement, tAttrs, transclude) { ... }
function link(scope, iElement, iAttrs, controller) { ... }
6.2.5指令的划分作用域参数:scope
为了实现这样的功能,我们需要使用scope参数,下面来介绍一下。
顾名思义,scope肯定是跟作用域有关的一个参数,它的作用是描述指令与父作用域的关系,这个父作用域是指什么呢?想象一下我们使用指令的场景,页面结构应该是这个样子:
<say-hello speak="content">美女</say-hello>
外层肯定会有一个controller,而在controller的定义中大体是这个样子:
var app = angular.module('MyApp', [], function(){console.log('here')});
app.controller('testC',function($scope){
所谓sayHello的父作用域就是这个名叫testC的控制器所管辖的范围,指令与父作用域的关系可以有如下取值:
取值 |
说明 |
false |
默认值。使用父作用域作为自己的作用域 |
true |
新建一个作用域,该作用域继承父作用域 |
javascript对象 |
与父作用域隔离,并指定可以从父作用域访问的变量 |
attributeName1: 'BINDING_STRATEGY',
attributeName2: 'BINDING_STRATEGY',...
键为属性名称,值为绑定策略。等等!啥叫绑定策略?最讨厌冒新名词却不解释的行为!别急,听我慢慢道来。
符号 |
说明 |
举例 |
@ |
传递一个字符串作为属性的值 |
str : ‘@string’ |
= |
使用父作用域中的一个属性,绑定数据到指令的属性中 |
name : ‘=username’ |
& |
使用父作用域中的一个函数,可以在指令中调用 |
getName : ‘&getUserName’ |
总之就是用符号前缀来说明如何为指令传值。你肯定迫不及待要看例子了,我们结合例子看一下,小二,上栗子~
我想要实现上面想像的跟美女多说点话的功能,即我们给sayHello指令加一个属性,通过给属性赋值来动态改变说话的内容 主要代码如下:
app.controller('testC',function($scope){
app.directive('sayHello',function(){
template: '<div>hello,<b ng-transclude></b>,{{ cont }}</div>',
<say-hello speak=" content ">美女</say-hello>
① 指令被编译的时候会扫描到template中的{ {cont} },发现是一个表达式;
② 查找scope中的规则:通过speak与父作用域绑定,方式是传递父作用域中的属性;
③ speak与父作用域中的content属性绑定,找到它的值“今天天气真好!”;
这样我们说话的内容content就跟父作用域绑定到了一其,如果动态修改父作用域的content的值,页面上的内容就会跟着改变,正如你点击“换句话”所看到的一样。
这个例子也太小儿科了吧!简单虽简单,但可以让我们理解清楚,为了检验你是不是真的明白了,可以思考一下如何修改指令定义,能让sayHello以如下两种方式使用:
<span say-hello speak="content">美女</span>
<span say-hello="content" >美女</span>
答案我就不说了,简单的很。下面有更重要的事情要做,我们说好了要写一个真正能用的东西来着。接下来就结合所学到的东西来写一个折叠菜单,即点击可展开,再点击一次就收缩回去的菜单。
app.controller('testC',function($scope){
$scope.text = '大家好,我是一名前端工程师,我正在研究AngularJs,欢迎大家与我交流';
app.directive('expander',function(){
templateUrl : 'expanderTemp.html',
link : function(scope,element,attris){
scope.toggleText = function(){
scope.showText = ! scope.showText;
<script type="text/ng-template" id="expanderTemp.html">
<div class="mytitle" ng-click="toggleText()">
<div ng-transclude ng-show="showText">
<expander etitle="title">{{text}}</expander>
上面的例子中,scope参数使用了=号来指定获取属性的类型为父作用域的属性,如果我们想在指令中使用父作用域中的函数,使用&符号即可,是同样的原理。
6.2.6指令间通信参数:controller和require
controller参数用于定义指令对外提供的接口,它的写法如下:
controller: function controllerConstructor($scope, $element, $attrs, $transclude)
所需要了解的知识点就这些,接下来是例子时间,依旧是从书上抄来的一个例子,我们要做的是一个手风琴菜单,就是多个折叠菜单并列在一起,此例子用来展示指令间的通信再合适不过。
首先我们需要定义外层的一个结构,起名为accordion,代码如下:
app.directive('accordion',function(){
template : '<div ng-transclude></div>',
this.gotOpended = function(selectedExpander){
angular.forEach(expanders,function(e){
this.addExpander = function(e){
app.directive('expander',function(){
templateUrl : 'expanderTemp.html',
link : function(scope,element,attris,accordionController){
accordionController.addExpander(scope);
scope.toggleText = function(){
scope.showText = ! scope.showText;
accordionController.gotOpended(scope);
后在toggleText方法中,除了要把自己的showText修改以外,还要调用accordionController的gotOpended方法通知父层指令把其他菜单给收缩起来。
<expander ng-repeat="expander in expanders" etitle="expander.title">
text: '大家好,我是一名前端工程师,我正在研究AngularJs,欢迎大家与我交流'},
6.3 性能及调优
6.3.1性能测试
AnglarJS作为一款优秀的Web框架,可大大简化前端开发的负担。
AnglarJS很棒,但当处理包含复杂数据结构的大型列表时,其运行速度就会非常慢。
AngularJS 中的ng-repeat在处理大型列表时,速度为什么会变慢?
// Post repeat directive for logging the rendering time
angular.module('siApp.services').directive('postRepeatDirective',
['$timeout', '$log', 'TimeTracker',
function($timeout, $log, TimeTracker) {
return function(scope, element, attrs) {
var timeFinishedLoadingList = TimeTracker.reviewListLoaded();
var ref = new Date(timeFinishedLoadingList);
$log.debug("## DOM rendering list took: " + (end - ref) + " ms");
<tr ng-repeat="item in items" post-repeat-directive>…</tr>
缓解该问题,最好的办法是限制所显示列表的大小。可通过分页、添加无限滚动条来实现。
6.3.2七大调优法则
这是最明显的解决方案,因为数据绑定是性能问题最可能的根源。如果你只想显示一次列表,并不需要更新、改变数据,放弃数据绑定是绝佳的办法。不过可惜的是,你会失去对数据的控制权,但除了该法,我们别无选择。
l <li ng-repeat="item in filteredItems()"> //这并不是一个好方法,因为要频繁地评估。
l <li ng-repeat="item in items"> //这是要采用的方法
var items = [{name:"John", active:true }, {name:"Adam"}, {name:"Chris"}, {name:"Heather"}];
$scope.displayedItems = items;
var filteredLists['active'] = $filter('filter)(items, {"active" : true});
$scope.applyFilter = function(type) {
if (filteredLists.hasOwnProperty(type){ // Check if filter is cached
$scope.displayedItems = filteredLists[type];
$scope.resetFilter = function() {
$scope.displayedItems = items;
<button ng-click="applyFilter('active')">Select active</button>
<ul><li ng-repeat="item in displayedItems">{{item.name}}<li></ul>
<li ng-repeat="item in items">
<button ng-click="item.showDetails = !item.showDetails">Show details</buttons>
<div ng-if="item.showDetails">
5.不要使用ng-mouseenter、ng-mouseleave等指令
大部分情况下,这样做很好,但一旦用户经常过滤,或者列表非常巨大,不断的链接与
触发ng-show的方法之一是使用表达式语法。ng-show的值由表达式语法来确定。可以看下面的例子:
<input ng-model="query"></input>
<li ng-repeat="item in items" ng-show="([item.name] | filter:query).length"> {{item.name}} </li>
<span style="font-size: 14px; line-height: 24px; font-family:; white-space: normal;"></span>
// Watch the queryInput and debounce the filtering by 350 ms.
$scope.$watch('queryInput', function(newValue, oldValue) {
if (newValue === oldValue) { return; }
$scope.filter.query = $scope.query;
<input ng-model="queryInput"/>
<li ng-repeat= item in items | filter:filter.query>{{ item.title }} </li>
7 总结
angular上手比较难,初学者(特别是习惯了使用JQuery的人)可能不太适应其语法以及思想。随着对ng探索的一步步深入,也确实感觉到了这一点,尤其是框架内部的某些执行机制。
7.1页面效果
7.2委派事件(代理事件)
7.2.1 NG循环及事件绑定
7.2.2 jQuery委派事件
从jQuery1.7开始,提供了.on()附加事件处理程序。
.on( events [, selector ] [, data ], handler(eventObject) )
参数Selector为一个选择器字符串,用于过滤出被选中的元素中能触发事件的后代元素。如果选择器是 null 或者忽略了该选择器,那么被选中的元素总是能触发事件。
如果省略selector或者是null,那么事件处理程序被称为直接事件 或者 直接绑定事件 。每次选中的元素触发事件时,就会执行处理程序,不管它直接绑定在元素上,还是从后代(内部)元素冒泡到该元素的。
委托事件有两个优势:他们能在后代元素添加到文档后,可以处理这些事件;代理事件的另一个好处就是,当需要监视很多元素的时候,代理事件的开销更小。
例如,在一个表格的 tbody 中含有 1,000 行,下面这个例子会为这 1,000 元素绑定事
$("#dataTable tbody tr").on("click", function(event){ alert($(this).text());});
委派事件的方法只有一个元素的事件处理程序,tbody,并且事件只会向上冒泡一层(从被点击的tr 到 tbody ):
$("#dataTable tbody").on("click", "tr", function(event){ alert($(this).text());});
转载自https://blog.csdn.net/weixin_33178524/article/details/79179597
angularjs详解相关推荐
- AngularJS 详解Directive(指令)机制
AngularJS 5个实例详解Directive(指令)机制 大漠穷秋 http://damoqiongqiu.iteye.com/blog/1917971 1.一点小说明 指令的作用:实现语义 ...
- AngularJS自定义指令详解(有分页插件代码)
前言 除了 AngularJS 内置的指令外,我们还可以创建自定义指令. 通过 .directive() 函数来添加自定义的指令. 调用自定义指令时,需要在HTMl 元素上添加自定义指令名. 自定义指 ...
- angularjs directive 实例 详解
angularjs directive 实例 详解 张映 发表于 2014-03-13 前面提到了angularjs的factory,service,provider,这个可以理解成php的model ...
- 【转】angularjs指令中的compile与link函数详解
这篇文章主要介绍了angularjs指令中的compile与link函数详解,本文同时诉大家complie,pre-link,post-link的用法与区别等内容,需要的朋友可以参考下 通常大家在使用 ...
- php theme_path,PHP_Yii2主题(Theme)用法详解,本文实例讲述了Yii2主题(Theme) - phpStudy
Yii2主题(Theme)用法详解 本文实例讲述了Yii2主题(Theme)用法.分享给大家供大家参考,具体如下: 首先看看主要的配置方式: 'components' => [ 'view' = ...
- angular元素属性绑定_AngularJS语法基础及数据绑定——详解各种数据绑定指令、属性应用...
AngularJS简单易学,但是功能强大.特别是在构建单页面应用方面效果显著.而 数据绑定 可以说是他被广泛使用的最主要的优点.他舍弃了对DOM的操作方式,一切都由AngularJS来自动更新视图,我 ...
- angular字符串转成html,详解angular如何调用HTML字符串的方法
详解angular如何调用HTML字符串的方法 前面的文章我们介绍过angular6.0的数据绑定,也就是前面页面如何调用后台的数据,我们接触到了调用普通数据--如:调用产品详情{{post.cont ...
- python接口自动化(十)--post请求四种传送正文方式(详解)
简介 post请求我在python接口自动化(八)–发送post请求的接口(详解)已经讲过一部分了,主要是发送一些较长的数据,还有就是数据比较安全等.我们要知道post请求四种传送正文方式首先需要先了 ...
- colsure php_PHP_PHP中Closure类的使用方法及详解,Closure,匿名函数,又称为Anonym - phpStudy...
PHP中Closure类的使用方法及详解 Closure,匿名函数,又称为Anonymous functions,是php5.3的时候引入的.匿名函数就是没有定义名字的函数.这点牢牢记住就能理解匿名函 ...
最新文章
- 突然而降的福利,看看你砸到没...
- Linux系统编程之查看文件大小的方法(lseek_fseek_stat)
- 6a标准 api_【阀门标准】API SPEC 6A CHINESE-2010中文版.pdf
- 5.5 关于数据的问题
- 20应用统计考研复试要点(part41)--概率论与数理统计
- 罗马数字 java_【leetcode刷题】[简单]13.罗马数字转整数(roman to integer)-java
- 1058 选择题 (20 分)
- 线性表:顺序栈算法实现
- RDS查看Binlog日志内容
- pg数据库多表查询(inner)和级联查询
- 将网页内容保存为PDF及为PDF创建多级书签
- Linux 用户必须知道的 14 个常用 Linux 终端快捷键
- mysql or 索引失效_MySQL索引失效的几种情况详析
- PT站的分享精神,我所向往的PT分享模式(原创)
- 新浪微博开放平台站内应用开发流程直播(一)
- CAD图如何导入Visio
- 反差检测自动对焦(CDAF)与相位检测自动对焦(PDAF)原理
- Nacos注册中心AP架构源码(Distro)下篇
- java面试宝典2017
- 苹果id提示购买无法完成怎么办?