AngularJS1.x入门·常用指令以及自定义指令

==AngularJS入门系列博客仅作入门快速开发参考,深层次的内容有待补充==

常用指令

  1. 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>
  1. 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>
  1. ng-controller:指定controller的作用范围
  2. ng-dblclick:双击事件,用法同ng-click。
  3. 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>
  1. 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>
  1. ng-repeat:遍历。

<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 />
        
    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:'Hello Angular ... ',
                replace:true,
                transclude:false
            };
        });
    script>
body>

解析:
1. 使用 directive 函数创建一个新的指令,名为hello。注意如果创建的指令名称是驼峰的。如创建指令 app.directive(‘helloWorld’,function(){ … });则在使用的时候需要用 ‘-’ 来连接,

<span hello-world>span>
  1. directive函数返回一个对象。restrict 定义了指令的识别规则。
    • A 识别attribute,作为属性名使用。
    • E 识别Element,作为标签使用。
    • C 识别class,作为class使用。
    • M 识别注释,作为注释来使用,两边要有空格。
      ==推荐使用 A E==
  2. template 指令显示的内容模板。
  3. replace 标记了该指令的HTML元素中的内容是否覆盖为模板中的内容。
  4. transclude 如果为true,则意味着你想要指令内部的内容嵌套到模板中而不是直接覆盖掉,如果transclude为true,则需要在模板中提供一个带有ng-transclude指令的容器(可以div或span)来存放指令内部内容。例如:
app.directive('hello',function(){
    return {
        restrict:'ACEM',
        template:'Hello Angular ... ',
        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>countbutton>
    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:'

指令私有scope中的值:{{name}}

'
, 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:'@'
    ...
}
...


...
<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:'

'
}; });
script> body>

解析:将外层indexController的scope中的sayEnglisg()方法传递给了指令,指令内部在调用say() 方法时,实际调用的是 sayEnglish();

你可能感兴趣的:(angularjs1.x)