==AngularJS入门系列博客仅作入门快速开发参考,深层次的内容有待补充==
常用指令
- ng-change:元素值改变的时候出发监听事件
<!-- 动态改变数量,计算总价 -->
<body ng-app="main">
<div ng-controller="indexController">
单价10,数量<input ng-model="num" ng-change="changeHello()" />,总价<input ng-model="total" />
</div>
<script type="text/javascript" src="../js/angular-1.6.4/angular.min.js"></script>
<script type="text/javascript"> var app = angular.module("main", []); app.controller("indexController", ['$scope', function($scope) { $scope.total=$scope.num*10; $scope.num=1; $scope.changeHello = function() { $scope.total=10*$scope.num }; }]); </script>
</body>
- ng-class:根据变量布尔值动态显示class
<!-- CSS -->
.red{color:#DD1144;}
.blue{color:#0000FF}
ng-class里面的表达式:当模型中 showRed为true时显示 .red样式,当showBlue为true时,显示 .blue样式。点击按钮,触发changeColor函数,true变false,false变true,实现动态切换css样式。
<body ng-app="main">
<div ng-controller="indexController">
<p ng-class="{'red':showRed,'blue':showBlue}">可以变色的字体</p>
<button class="btn btn-primary" ng-click="changeColor()">改变颜色</button>
</div>
<script type="text/javascript" src="../js/angular-1.6.4/angular.min.js"></script>
<script type="text/javascript"> var app = angular.module("main", []); app.controller("indexController", ['$scope', function($scope) { $scope.showRed=true; $scope.showBlue=false; $scope.changeColor=function(){ $scope.showRed=!$scope.showRed; $scope.showBlue=!$scope.showBlue; }; }]); </script>
</body>
- ng-controller:指定controller的作用范围
- ng-dblclick:双击事件,用法同ng-click。
-
ng-hide/ng-show:动态显示或隐藏
以上例子可改为动态显示不同颜色的字体
<!-- 其他的代码同上面的例子 -->
<div ng-controller="indexController">
<p class="red" ng-show="showRed">可以变色的字体</p>
<p class="blue" ng-hide="showRed">可以变色的字体</p>
<button class="btn btn-primary" ng-click="changeColor()">改变颜色</button>
</div>
- ng-keypress:监听按键事件。例如监听input搜索框中按下回车键开始关键字搜索
<!-- 将关键词属性绑定在模型中,判断如果是回车键被按下时,则根据关键字搜索。 -->
<body ng-app="main">
<div ng-controller="indexController">
<input type="text" ng-model="keyword" ng-keypress="search($event)" />
</div>
<script type="text/javascript" src="../js/angular-1.6.4/angular.min.js"></script>
<script type="text/javascript"> var app = angular.module("main", []); app.controller("indexController", ['$scope', function($scope) { $scope.keyword=""; $scope.search=function($event){ if(13==$event.keyCode){ alert("正在根据 "+$scope.keyword+" 开始搜索 ... "); } }; }]); </script>
</body>
- ng-repeat:遍历。
<!-- 遍历书的集合显示为ul列表 -->
<body ng-app="main">
<div ng-controller="indexController">
<ul>
<li ng-repeat="item in books">
{{item}}
</li>
</ul>
</div>
<script type="text/javascript" src="../js/angular-1.6.4/angular.min.js"></script>
<script type="text/javascript"> var app = angular.module("main", []); app.controller("indexController", ['$scope', function($scope) { $scope.books=['Java','Javascript','python','Mysql']; }]); </script>
</body>
自定义指令
首先看几个个最简单的指令例子:
示例1:固定的模板内容显示
<body ng-app="main">
<div ng-controller="indexController">
<span hello>该文本被替换</span> <br />
<hello>该文本被替换</hello> <br />
<span class="hello">该文本被替换</span><br />
<!-- directive:hello -->
</div>
<script type="text/javascript" src="../js/angular-1.6.4/angular.min.js"></script>
<script type="text/javascript"> var app = angular.module("main", []); app.directive('hello',function(){ return { restrict:'ACEM', template:'<span>Hello Angular ... </span>', replace:true, transclude:false }; }); </script>
</body>
解析:
1. 使用 directive 函数创建一个新的指令,名为hello。注意如果创建的指令名称是驼峰的。如创建指令 app.directive(‘helloWorld’,function(){ … });则在使用的时候需要用 ‘-’ 来连接,
<span hello-world></span>
- directive函数返回一个对象。restrict 定义了指令的识别规则。
- A 识别attribute,作为属性名使用。
- E 识别Element,作为标签使用。
- C 识别class,作为class使用。
- M 识别注释,作为注释来使用,两边要有空格。
==推荐使用 A E==
- template 指令显示的内容模板。
- replace 标记了该指令的HTML元素中的内容是否覆盖为模板中的内容。
- transclude 如果为true,则意味着你想要指令内部的内容嵌套到模板中而不是直接覆盖掉,如果transclude为true,则需要在模板中提供一个带有ng-transclude指令的容器(可以div或span)来存放指令内部内容。例如:
app.directive('hello',function(){
return {
restrict:'ACEM',
template:'<span>Hello Angular ... <span ng-transclude></span></span>',
replace:false,
transclude:true
};
});
当你这样使用时
<span hello>内部的文本不会被直接覆盖而被包裹到模板中带有ng-transclude指令的标签中</span>
页面会显示
Hello Angular ... 内部的文本不会被直接覆盖而被包裹到模板中带有ng-transclude指令的标签中
示例2:DOM绑定事件
<body ng-app="main">
<div ng-controller="indexController">
<p ng-bind="count"></p>
<button class="btn btn-primary" hello>count</button>
</div>
<script type="text/javascript" src="../js/angular-1.6.4/angular.min.js"></script>
<script type="text/javascript"> var app = angular.module("main", []); app.controller("indexController", ['$scope', function($scope) { $scope.count=1; }]); app.directive('hello',function(){ return { restrict:'A', link:function(scope,element,attrs){ element.on('click',function(){ scope.$apply(function(){ scope.count++; }); }); } }; }); </script>
</body>
scope上初始化count属性并赋值1,p标签绑定count,hello指令:带有hello指令的元素绑定click事件,点击一次count加1。
解析:
link:通常在link函数中封装对dom的操作。参数:
1. scope:未直接指明scope作用域时,此scope共享controller的scope。
2. element:指标记了该指令的且由angular封装后的元素,封装了基本的方法,跟jQuery封装的用法差不多。
3. attrs:标记了该指令的元素的所有属性封装的对象。比如本例子中,标记了hello指令的button带有class属性,可以使用attrs.class 取出class属性的值。!!!注意一个坑,这个地方的属性名称会全部转成小写字母,如果你的属性名中有大写,一定要注意。
4. click函数中调用了
scope.$apply(function(){ … })
如果我们去掉这个外层的包裹,直接在click函数中写 scope.count++
;会发现页面上的count值没有变化,但是在浏览器debug js的时候发现scope中的值其实已经改变了,只是页面没有做出响应。我们可以想一下,如果我们自己来实现angular的双向数据绑定,至少要有两步:1.监听数据模型与视图的变化。2.当视图数据有变时通知model更新model数据,当model数据有变时通知视图去更新视图内容。$apply()
就是其实干这个通知的事的,具体的实现原理后面我们再探讨,他的入参是一个函数。
什么情况下需要调用这个$apply()
呢?大多数情况下无需手动调用,在使用angular自带的指令比如ng-click,angular内置的服务如$http() ``$timeout()
的时候,angular已经为我们调用了这个函数,我们使用的时候无需调用,如果手动调用反而会报错。而上面的例子我们没有使用angular的指令或服务,而是普通的事件监听,所以$apply()
需要手动调用。
示例3:指令独立scope
<body ng-app="main">
<div ng-controller="indexController">
<p>{{username}}</p>
<p hello>
{{username}}
</p>
</div>
<script type="text/javascript" src="../js/angular-1.6.4/angular.min.js"></script>
<script type="text/javascript"> var app = angular.module("main", []); app.controller("indexController", ['$scope', function($scope) { }]); app.directive('hello',function(){ return { scope:true, /*或者 scope:{} 都表示指令声明了自己独立的scope*/ restrict:'A', controller:function($scope){ $scope.username='Mike'; } }; }); </script>
</body>
还是hello指令,不同的是在自定义指令中返回的对象中设置了==scope:true==,表示声明指令的scope是私有的,并为指令创建了独立的控制器,为私有scope赋值username属性为Mike,在页面上在hello指令下取 username 是可以取到的,但是在hello指令外取的username是没有值的。
示例4:指令独立scope中的数据绑定外层controller的scope策略
‘@’ +{{}}策略: :字符串传递,数据单向绑定,当修改指令外层scope中的模型数据时指令内部绑定的模型值会改变,但是修改指令内部的模型值时外层不会改变;
<body ng-app="main">
<div ng-controller="indexController">
<p>{{username}}</p>
indexController下的scope值 <input type="text" ng-model="username" />
<p hello name="{{username}}">
指令私有scope: {{name}}
</p>
</div>
<script type="text/javascript" src="../js/jquery1.12.4.min.js"></script>
<script type="text/javascript" src="../js/angular-1.6.4/angular.min.js"></script>
<script type="text/javascript"> var app = angular.module("main", []); app.controller("indexController", ['$scope', function($scope) { $scope.username="Lily"; }]); app.directive('hello',function(){ return { scope:{ name:'@' }, restrict:'A', relplace:true, template:'<p><p>指令私有scope中的值:{{name}}<p><button class="btn btn-primary">change private</button></p>', link:function(scope,ele,attrs){ $(ele).find("button").on("click",function(){ scope.$apply(function(){ scope.name="Mike"; }); }); } }; }); </script>
</body>
这个例子中引入了jQuery。
解析:将indexController的scope中的username的值传递给了自定义指令hello,input框绑定的是indexController的scope中的模型,指令我们为指令模板中的button添加点击事件,当点击按钮时,改变私有scope中name的值。
运行结果:当我们在input框中改变可以看到指令所有scope中的值也会响应变化,因为@绑定策略就是将模型的值传递给指令,字符串传递。但是当我们点击按钮改变私有scope的name的值的时候,indexController的scope是不会响应这种变化的
‘=’ 策略:模型对象传递
<!-- 修改上述例子的指令里面的scope中的name绑定策略为 ‘=’-->
...
scope:{
name:'@'
...
}
...
<!--页面上绑定的方式改为:-->
...
<p hello name="username">
...
解析:‘=’绑定策略传递的是对象
运行结果:两个scope中模型的值是双向绑定的,改变任何一个,另一个也会响应这种变化。
‘&’ 策略:函数传递,指令调用
<body ng-app="main">
<div ng-controller="indexController">
<p hello say="sayEnglish()"></p>
</div>
<script type="text/javascript" src="../js/angular-1.6.4/angular.min.js"></script>
<script type="text/javascript"> var app = angular.module("main", []); app.controller("indexController", ['$scope', function($scope) { $scope.sayEnglish=function(){ alert('Good Morning!'); }; }]); app.directive('hello',function(){ return { scope:{ say:'&' }, restrict:'A', relplace:true, template:'<p><button class="btn btn-primary" ng-click="say()">打声招呼</button></p>' }; }); </script>
</body>
解析:将外层indexController的scope中的sayEnglisg()方法传递给了指令,指令内部在调用say() 方法时,实际调用的是 sayEnglish();