【angularJS】Directive指令

  AngularJS 通过被称为 指令 的新属性来扩展 HTML。指令是扩展的 HTML 属性,带有前缀 ng-

内置指令

1ng-app 指令初始化一个 AngularJS 应用程序。

      定义了 AngularJS 应用程序的 根元素

2ng-init 指令初始化应用程序数据。

      通常情况下,不使用 ng-init。您将使用一个控制器或模块来代替它。

3ng-model 指令把元素值(比如输入域的值)绑定到应用程序【一般是在控制器中定义的变量】。

4ng-repeat 指令会重复一个 HTML 元素:

      对于集合中(数组中)的每个项会 克隆一次 HTML 元素

      names=['Jani','Hege','Kai'] 

<ul>
    <li ng-repeat="x in names">
      {{ x }}
    </li>
  </ul>

HTML DOM指令

AngularJS 为 HTML DOM 元素的属性提供了绑定应用数据的指令。

5ng-disabled 指令 直接绑定应用程序数据到 HTML 的 disabled 属性,不可用

<div ng-app="" ng-init="mySwitch=true">

<p><button ng-disabled="mySwitch">点我!</button></p>

<p><input type="checkbox" ng-model="mySwitch"/>按钮</p>

<p>

{{ mySwitch }}

</p>

ng-disabled 指令 绑定应用程序数据 "mySwitch" 到 HTML 的 disabled 属性。

ng-model 指令 绑定 "mySwitch" 到 HTML input checkbox 元素的内(value),只能是true或者false。

6ng-show 指令隐藏或显示一个 HTML 元素。

您可以使用一个评估为 true or false 的表达式(比如 ng-show="hour < 12")来隐藏和显示 HTML 元素。

ng-hide 指令用于设置应用的一部分 不可见 。

ng-hide="true" 让 HTML 元素 不可见

ng-hide="false" 让元素可见。

7ng-click 指令定义了一个 AngularJS 单击事件

8、ng-view指令

<div ng-view></div>

该 div 内的 HTML 内容会根据路由的变化而变化。

自定义指令

除了 AngularJS 内置的指令外,我们还可以创建自定义指令。

你可以使用 .directive 函数来添加自定义的指令。

要调用自定义指令,HTML 元素上需要添加自定义指令名。

使用驼峰法来命名一个指令, runoobDirective, 但在使用它时需要以 - 分割, runoob-directive:

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<script src="https://cdn.bootcss.com/angular.js/1.4.6/angular.min.js"></script> 
</head>
<body ng-app="myApp">
<runoob-directive></runoob-directive>
<script>
var app = angular.module("myApp", []);
app.directive("runoobDirective", function() {
    return {
        template : "<h1>自定义指令!</h1>"
    };
});
</script>
</body>
</html>
View Code

 

指令的作用到底是什么呢?

假如我们有几个控制器都需要用到相同指令但是对应不同事件时,此时难道需要定义不同的指令吗?答案肯定很显然不是,指令说到底就是为了【view复用】。

 当需要复用指令时,可以通过获取指令上属性对应的方法,最终利用apply方法应用到对应的控制器中。

var app = angular.module('app', []);

    app.controller("first",["$scope",function($scope){
        $scope.first = function(){
            alert("第一个控制器函数");
        }
    }])

    app.controller("second",["$scope",function($scope){
        $scope.second = function(){
            alert("第二个控制器函数");
        }
    }])

    app.directive('lay', function(){
        return{
              restrict:"AE",
              link:function(scope,element,attr){
                  element.on("click",function(){
                      scope.$apply(attr.loader);  //给指令添加属性loader
                  })
              }
        };
    });
<div ng-controller="first">
    <lay loader="first()">第一个控制器</lay>
</div>
<br/>
<div ng-controller="second">
    <lay loader="second()">第二个控制器</lay>
</div>
View Code

指令定义参数详解

参考:https://www.cnblogs.com/CreateMyself/p/5153772.html

.directive('ngDirective', ['', function(){

        // Runs during compile

        return {

            // name: '',

            // priority: 1,

            // terminal: true,

            // scope: {}, // {} = isolate, true = child, false/undefined = no change

            // controller: function($scope, $element, $attrs, $transclude) {},

            // require: 'ngModel', // Array = multiple requires, ? = optional, ^ = check parent elements

            // restrict: 'A', // E = Element, A = Attribute, C = Class, M = Comment

            // template: '',

            // templateUrl: '',

            // replace: true,

            // transclude: true,

            // compile: function(tElement, tAttrs, function transclude(function(scope, cloneLinkingFn){ return function linking(scope, elm, attrs){}})),

            link: function($scope, iElm, iAttrs, controller) {          

            }

        };

    }]);

各属性含义:

1、name

指令名,就是ngDirective,在html中使用时用ng-directive

注意这里的大小写,js中是驼峰命名。Html中全小写。

指令名字的书写

ngOfflineDatepicker   html中 ng-offline-datepicker

 

2、restrict

意思是替换的是什么,【E】:元素,【A】:属性,【C】:类名,【M】:注释。

E:<ng-Directive></ng-Directive> 
A:<div ng-Directive></div>
C:<p class="ng-Directive"></p>
M:<!-- directive: ng-Directive  -->在注释中的ng-Directive和后面的--之间要有间隔

3、replace:

true 时,restrict的替换才能成功

4、template

(模板)自然就不用说了。

5、tepmlateUrl

在实际开发中用template形式来给出模板似乎不太友好,一旦替换的内容比较多那么显得代码比较凌乱,此时我们就要用到templateUrl,将模板单独写在一个页面即可。这个就不用说了,在这个内容不得不说的是模板的缓存。

var app = angular.module('app', []);

    app.run(function($templateCache){

        $templateCache.put("hello.html","<h1>hello cnblogs</h1>")

    });

    app.directive("hello",function($templateCache){

        return{

            restrict:"AE",

            template:$templateCache.get("hello.html"),

            replace:true

        };

});

6、scope属性

directive隔离Scope数据交互: https://blog.coding.net/blog/angularjs-directive-isolate-scope

directive 默认能共享 scope 中定义的属性,例如在模版中直接使用 scope 中的对象和属性。通常使用这种直接共享的方式可以实现一些简单的 directive 功能。

但是,当你要创建一个可以重复使用的directive的时候,就不能依赖于父scope了,因为在不同的地方使用directive对应的父scope不一样。

当你需要创建一个可重复使用的 directive,只是偶尔需要访问或者修改父 scope 的数据,就需要使用隔离 scope。当使用隔离 scope 的时候,directive 会创建一个没有依赖父 scope 的 scope,并提供一些访问父 scope 的方式。

共享 scope 可以直接共享父 scope,而隔离 scope 无法共享父scope。

l  如何在 directive 中创建隔离 scope

所以你需要一个隔离的scope,我们可以向下面这样来定义我们的scope。

module1.directive("testDirective", function () {

        return {

            scope: {

                value: '提莫队长正在待命!'

                         },

            template: 'Say:{{value}}'

        }

});

这样就很方便的将我们directive的上下文scope给定义出来了【标红的地方】,但是,如果我想将父scope中的属性传递给directive的scope怎么办呢?

l  隔离 scope 和父 scope 如何交互

directive 在使用隔离 scope 的时候,提供了三种方法同隔离之外的地方交互。这三种分别是 

  • @ 绑定一个局部 scope 属性到当前 dom 节点的属性值。结果总是一个字符串,因为 dom 属性是字符串。【eg,绑定name:’@’,到dom节点的name=”{{name}}”】
  • & 提供一种方式执行一个表达式在父 scope 的上下文中。如果没有指定 attr 名称,则属性名称为相同的本地名称。
  • = 通过 directive 的 attr 属性的值在局部 scope 的属性和父 scope 属性名之间建立双向绑定。

局部 scope 属性

@ 方式局部属性用来访问 directive 外部环境定义的字符串值,主要是通过 directive 所在的标签属性({{name}})绑定外部字符串值。这种绑定是单向的,即父 scope 的绑定变化,directive 中的 scope 的属性会同步变化,而隔离 scope 中的绑定变化,父 scope 是不知道的。

如下示例:directive 声明未隔离 scope 类型,并且使用@绑定 name 属性,在 directive 中使用 name 属性绑定父 scope 中的属性。当改变父 scope 中属性的值的时候,directive 会同步更新值,当改变 directive 的 scope 的属性值时,父 scope 无法同步更新值。

js 代码

app.controller("myController", function ($scope) {

        $scope.name = "hello world";

    }).directive("isolatedDirective", function () {

        return {

            scope: {

                name: "@"

            },

            template: 'Say:{{name}} <br>改变隔离scope的name:<input type="buttom" value="" ng-model="name" class="ng-pristine ng-valid">'

        }

})

html

<div ng-controller="myController">
   <div class="result">
       <div>父scope:
           <div>Say:{{name}}<br>改变父scope的name:<input type="text" value="" ng-model="name"/></div>
       </div>
       <div>隔离scope:
           <div isolated-directive name="{{name}}"></div>
       </div>
        <div>隔离scope(不使用{{name}}):
             <div isolated-directive name="name"></div>
         </div>
   </div>

局部 scope 属性

= 通过 directive 的 attr 属性的值在局部 scope 的属性和父 scope 属性名之间建立双向绑定。
意思是,当你想要一个双向绑定的属性的时候,你可以使用=来引入外部属性。无论是改变父 scope 还是隔离 scope 里的属性,父 scope 和隔离 scope 都会同时更新属性值,因为它们是双向绑定的关系。

局部 scope 属性

& 方式提供一种途经是 directive 能在父 scope 的上下文中执行一个表达式。此表达式可以是一个 function。
比如当你写了一个 directive,当用户点击按钮时,directive 想要通知 controller,controller 无法知道 directive 中发生了什么,也许你可以通过使用 angular 中的 event 广播来做到,但是必须要在 controller 中增加一个事件监听方法。
最好的方法就是让 directive 可以通过一个父 scope 中的 function,当 directive 中有什么动作需要更新到父 scope 中的时候,可以在父 scope 上下文中执行一段代码或者一个函数。

<div ng-controller="myController">
        <div ng-controller="myController">
            <div>
                父scope:
                <div>Say:{{value}}</div>
            </div>
            <div>
                隔离scope:
                <div isolated-directive action="click()"></div>
            </div>
        </div>
    </div>
    <script src="Scripts/angular.min.js"></script>
    <script>
        var app = angular.module("myApp", []);
        app.controller("myController", function ($scope) {
            $scope.value = "hello world";
            $scope.click = function () {
                $scope.value = Math.random();
            };
        }).directive("isolatedDirective", function () {
            return {
                scope: {
                    action: "&"
                },
                template: '<input type="button" value="在directive中执行父scope定义的方法" ng-click="action()"/>'
            }
        })
    </script>
View Code

 

7、require属性

【指令与页面上已定义控制器进行交互】

var app = angular.module('app', []);
    app.controller("ctrl",["$scope",function($scope){
        $scope.win = function(){
            alert("你赢了");
        }
    }])
    app.directive("lay",function(){
        return{
            restrict:"AE",
            scope:true,
            template:'<div>点击我,有惊喜哦</div>',
            replace:true,
            link:function(scope,elment,attr){
                elment.on("click",function(){
                    scope.win();
                })
            }
        };
    });
View Code

对于页面中已定义的控制器,指令为与其进行交互直接通过link上的scope来获取该控制器上的APi即可。

【指令与指令上控制器进行交互】

此时就需要用到require,此属性的作用是指令与指令之间的交互,说的更加具体一点就是与其他指令中控制器之间的交互。在指令中获取其他指令的控制器要用到link函数的第四个参数,link函数的前三个参数还是非常容易理解,不再叙述。那么是怎样在当前指令去获取该控制器呢?这时就需要用到require属性。

对于指令上的link与指令上的controller的何时使用,我们可以这样概括:当一个指令上想向外部暴露这个指令时,此时利用controller进行暴露,而其他指令需要利用指令时,通过属性requirelink上的第四个参数进行获取暴露指令的APi,否则的话我们不需要第四个参数。

8、link和controller属性

页面:

<custom-directive></custom-directive>

Js:

angular
    .module('app',[])
    .directive('customDirective', customDirective);

function customDirective() {
    var directive = {
        restrict: 'EA',
        template: '<div>xpy0928{{test}}</div>',
        link: directiveLink,
        controller:directiveController
    };

    return directive;
}

function directiveController($scope){
    $scope.test = " from contrller cnblogs";
}

function directiveLink(scope,elem,attr) {
    scope.test = scope.test + ",and from link cnblogs";
}
View Code

结论:编译之前执行控制器(controller),编译之后执行链接(link)。

由此我们可以基本得出在controller和link中应该写什么代码的结论:

(1)在controller写业务逻辑(我们明白业务逻辑大部分是放在服务中),这里所说的业务逻辑乃是为呈现视图之前而准备的数据或者是与其他指令进行数据交互而暴露这个api。

(2)在link中主要操作DOM。用来处理dom渲染前后的一些事情,

在这个函数里我们可以获取dom结构等信息

link参数,这参数要求声明一个函数,称之为链接函数。

写法:

link: function(scope, element, attrs) {
  // 在这里操作DOM
}

如果指令使用了require选项,那么链接函数会有第四个参数,代表控制器或者所依赖的指令的控制器。

// require 'SomeController',
link: function(scope, element, attrs, SomeController) {
  // 在这里操作DOM,可以访问required指定的控制器
}

链接函数之所以能够在指令中操作DOM,就是因为传入的这几个参数:scope、element、attrs

scope:即与指令元素相关联的当前作用域,可以用来注册监听器:scope.$watch()

element:即当前指令对应的元素,使用它可以操作该元素及其子元素。例如<span my-directive></span>,这个span就是指令 my-directive所使用的元素。

attrs:由当前元素的属性组成的对象。

 

Link中 添加CSS样式

link: function ($scope, element) {

            $scope.winowHeight = window.screen.height; //获取窗口高度

            element.css('height',$scope.winowHeight + 'px');

            element.css('margin-top', ($scope.winowHeight *0.3) + 'px')

        }

元素可操作的方法:

https://www.cnblogs.com/golddream/p/4932884.html

posted @ 2018-12-12 09:52  peterYong  阅读(1013)  评论(0编辑  收藏  举报