首页 > 代码库 > 2-8 指令

2-8 指令

2-8 指令

内容简介

  • 解析最简单的指令hello:匹配模式restrict

  • 解析最简单的指令hello:template、templateUrl、$templateCache

  • 解析最简单的指令hello:replace与translude

  • comile与link(操作元素、添加css样式、绑定事件)

  • 指令与控制器之间的交互

  • 指令间的交互

  • scope的类型与独立scope

  • scope的绑定策略

  • 实例解析Expander

  • 实例解析Accordion

  • 指令的运行原理:compile和link

  • 总结:ERP类型的系统必备的UI组件

  • 总结:互联网/电商型系统必备的UI组件

  • 第三方指令库angular-ui

  • Directive思想的起源和原理概述

1. 解析最简单的指令hello:匹配模式restrict

restrict:匹配模式。它有4个选项,分别为

  • A 属性attribute
  • E 元素element
  • M 注释comment
  • C 样式中的class

属性方式

<!DOCTYPE html><html lang="en"><head>    <meta charset="UTF-8">    <title>指令</title>    <script src="../node_modules/angular/angular.js"></script>    <script src="js/HelloAngular_Directive.js"></script></head><body ng-app="myApp"><div hello></div></body></html>
/** * Created by engoo-ypf on 2017/3/6. */var app=angular.module(‘myApp‘,[]);app.directive(‘hello‘,function () {    return{        restrict:‘A‘,        template:‘<div> hi everyone!</div>‘,        replace:true    }})

渲染后结果:
技术分享

元素方式

<!DOCTYPE html><html lang="en"><head>    <meta charset="UTF-8">    <title>指令</title>    <script src="../node_modules/angular/angular.js"></script>    <script src="js/HelloAngular_Directive.js"></script></head><body ng-app="myApp"><hello></hello></body></html>
/** * Created by engoo-ypf on 2017/3/6. */var app=angular.module(‘myApp‘,[]);app.directive(‘hello‘,function () {    return{        restrict:‘E‘,        template:‘<div> hi everyone!</div>‘,        replace:true    }})

渲染后结果:
技术分享

注释方式

<!DOCTYPE html><html lang="en"><head>    <meta charset="UTF-8">    <title>指令</title>    <script src="../node_modules/angular/angular.js"></script>    <script src="js/HelloAngular_Directive.js"></script></head><body ng-app="myApp"><!--  directive:hello --></body></html>

注意:指令``的写法。它的前后都有空格。这个坑一定要注意啊!!!

/** * Created by engoo-ypf on 2017/3/6. */var app=angular.module(‘myApp‘,[]);app.directive(‘hello‘,function () {    return{        restrict:‘M‘,        template:‘<div> hi everyone!</div>‘,        replace:true    }})

渲染后结果:
技术分享

样式方式

<!DOCTYPE html><html lang="en"><head>    <meta charset="UTF-8">    <title>指令</title>    <script src="../node_modules/angular/angular.js"></script>    <script src="js/HelloAngular_Directive.js"></script></head><body ng-app="myApp"><!--class样式指令--><div class="hello"></div></body></html>
/** * Created by engoo-ypf on 2017/3/6. */var app=angular.module(‘myApp‘,[]);app.directive(‘hello‘,function () {    return{        restrict:‘C‘,        template:‘<div> hi everyone!</div>‘,        replace:true    }})

渲染后:
技术分享

四种模式的使用场景

指令含义示例
A属性(默认)<div my-menu=‘Products‘></div>
E元素<my-menu title=Products></my-menu>
M注释<!-- directive:my-menu Products -->
C样式类<div class=‘my-menu:Products‘></div>
  • 推荐使用元素和属性的方式使用指令
  • 当需要创建带有自己的模板的指令时,使用元素名称的方式创建指令
  • 当需要为有的html标签增加功能时,使用属性的方式创建指令

2. 解析最简单的指令hello:template、templateUrl、$templateCache

当我们使用指令的时候,每次都要在js中去Template去写html会很痛苦。为此Angular为我们准备了templateUrl。

templateUrl

<!DOCTYPE html><html lang="en"><head>    <meta charset="UTF-8">    <title>Title</title>    <script src="../node_modules/angular/angular.js"></script>    <script src="js/templateUrl.js"></script></head><body ng-app="myApp"><hello></hello></body></html>
/** * Created by engoo-ypf on 2017/3/6. */var app=angular.module(‘myApp‘,[]);app.directive(‘hello‘,function () {    return{        reactive:‘E‘,        templateUrl:‘tpls/tpls1.html‘,        replace:true    }})
<div style="color: rebeccapurple; font-size: 50px">我是模板</div>

渲染后页面:
技术分享

$templateCache

如果我们编写的模板不仅仅是在现有的指令要使用,其他的指令也要使用该模板。我们就可以$templateCache。它可以将我们的模板进行缓存起来。

<!DOCTYPE html><html lang="en"><head>    <meta charset="UTF-8">    <title>Title</title>    <script src="../node_modules/angular/angular.js"></script>    <script src="js/templateCache.js"></script></head><body ng-app="myApp"><hello></hello></body></html>
/** * Created by engoo-ypf on 2017/3/6. */var app=angular.module(‘myApp‘,[]);// 注射器加载完所有模块时,此方法执行一次app.run(function ($templateCache) {    $templateCache.put(‘helloTemple.html‘,‘<div>hello everyone!!!</div>‘)});app.directive(‘hello‘,function ($templateCache) {    return{        restrict:‘E‘,        template:$templateCache.get(‘helloTemple.html‘),        replace:true    }})

3. 解析最简单的指令hello:replace与translude

前面我们都是使用replace来替换页面中内容,那么如果我们不想替换,而是想在里面追加。那么我就可以使用translude

<!DOCTYPE html><html lang="en"><head>    <meta charset="UTF-8">    <title>Title</title>    <script src="../node_modules/angular/angular.js"></script>    <script src="js/transclude.js"></script></head><body ng-app="myApp"><hello>    <div>我是页面内容</div></hello></body></html>
/** * Created by engoo-ypf on 2017/3/6. */var app=angular.module(‘myApp‘,[]);app.directive(‘hello‘,function () {    return{        restrict:‘E‘,        transclude:true,        template:‘<div>hello everyone! <div ng-transclude></div></div>‘    }})

4. comile与link(操作元素、添加css样式、绑定事件)

 

技术分享

1488784946835.jpg

技术分享

 

5. 指令与控制器之间的交互

采用link的方式来进行交互。

<!DOCTYPE html><html lang="en"><head>    <meta charset="UTF-8">    <title>Title</title>    <script src="../node_modules/angular/angular.js"></script>    <script src="js/Directive&Controller.js"></script></head><body ng-app="myApp"><div ng-controller="myCtrl">    <loader >滑动加载</loader></div></body></html>
/** * Created by engoo-ypf on 2017/3/6. */var app=angular.module(‘myApp‘,[]);app.controller(‘myCtrl‘,[‘$scope‘,function ($scope) {    $scope.loadData=http://www.mamicode.com/function () {        console.log(‘数据加载中~~~~‘);    }}])app.directive(‘loader‘,function () {    return{        restrict:‘AE‘,        link:function (scope,element,attr) {            //当鼠标滑动到该指令的时候,执行下面代码            element.bind(‘mouseenter‘,function () {                // scope.loadData();  直接调用                scope.$apply(‘loadData()‘) //也可以这样调用            })        }    }})

那么如果我们有多个指令需要调用不同的Controller中的function如何做呢?

<!DOCTYPE html><html lang="en"><head>    <meta charset="UTF-8">    <title>Title</title>    <script src="../node_modules/angular/angular.js"></script>    <script src="js/Directive&Controller.js"></script></head><body ng-app="myApp"><div ng-controller="myCtrl">    <loader howLoadData="loadData1()">滑动加载1</loader>    <loader howLoadData="loadData2()">滑动加载2</loader></div></body></html>
/** * Created by engoo-ypf on 2017/3/6. */var app=angular.module(‘myApp‘,[]);app.controller(‘myCtrl‘,[‘$scope‘,function ($scope) {    $scope.loadData1=function () {        console.log(‘数据1加载中~~~~‘);    }    $scope.loadData2=function () {        console.log(‘数据2加载中~~~~‘);    }}])app.directive(‘loader‘,function () {    return{        restrict:‘AE‘,        link:function (scope,element,attr) {            //当鼠标滑动到该指令的时候,执行下面代码            element.bind(‘mouseenter‘,function () {                // scope.loadData();				//这里有个坑:html中写的属性名字,在这里必须全部转成小写                scope.$apply(attr.howloaddata)            })        }    }})

6. 指令间的交互

<!DOCTYPE html><html lang="en"><head>    <meta charset="UTF-8">    <title>Title</title>    <script src="node_modules/angular/angular.js"></script>    <script src="src/js/Directive&Directive.js"></script></head><body ng-app="myApp"><div class="row">    <div class="col-md-3">        <superman strength>动感超人1---力量</superman>    </div></div><div class="row">    <div class="col-md-3">        <superman strength speed>动感超人2---力量+敏捷</superman>    </div></div><div class="row">    <div class="col-md-3">        <superman strength speed light>动感超人2---力量+敏捷+发光</superman>    </div></div></body></html>
/** * Created by engoo-ypf on 2017/3/6. */var app=angular.module(‘myApp‘,[]);app.directive(‘superman‘,function () {    return{        // 创建独立的作用域        scope:{},        restrict:‘AE‘,        // 指令内部的Controller。主要是用来暴露本身的方法供其它指令调用        controller:function ($scope) {            //给指令暴露出3个方法,以供其它指令调用            $scope.abilities=[];            this.addStrength=function () {                $scope.abilities.push(‘strength‘);            };            this.addSpeed=function () {                $scope.abilities.push(‘speed‘);            };            this.addLight=function () {                $scope.abilities.push(‘light‘);            };        },        link:function (scope,element,attrs) {            element.addClass(‘btn btn-primary‘);            element.bind(‘mouseenter‘,function () {                console.log(scope.abilities);            })        }    }})app.directive(‘strength‘,function () {    return{        //表示现在的指令时依赖于superman指令        require:‘^superman‘,        link:function (scope,element,attrs,supermanCtrl) {            supermanCtrl.addStrength();        }    }})app.directive(‘speed‘,function () {    return{        //表示现在的指令时依赖于superman指令        require:‘^superman‘,        link:function (scope,element,attrs,supermanCtrl) {            supermanCtrl.addSpeed();        }    }})app.directive(‘light‘,function () {    return{        //表示现在的指令时依赖于superman指令        require:‘^superman‘,        link:function (scope,element,attrs,supermanCtrl) {            supermanCtrl.addLight();        }    }})

7. scope的类型与独立scope

<!DOCTYPE html><html lang="en"><head>    <meta charset="UTF-8">    <title>Title</title>    <script src="../node_modules/angular/angular.js"></script>    <script src="js/isolateScope.js"></script></head><body ng-app="myApp"><hello></hello><hello></hello><hello></hello><hello></hello></body></html>
/** * Created by engoo-ypf on 2017/3/6. */var app = angular.module(‘myApp‘, []);app.directive(‘hello‘, function () {    return {        restrict: ‘AE‘,		//这是这句后,我们的指令中的scope就会独立使用,不会相互污染啦        scope: {},        template: ‘<div><input type="text" ng-model="userName"/>{{userName}}</div>‘,        replace: true    }})

8. Scope的绑定策略

参数解释
@把当前属性作为字符串传递(不能传递对象)。你还可以绑定来自外层scope的值,在属性值中插入{{}} 即可
=与父级scope中的属性进行双向绑定
&传递一个来自父级scope的函数,稍后调用

@绑定

<!DOCTYPE html><html lang="en"><head>    <meta charset="UTF-8">    <title>Title</title>    <script src="../node_modules/angular/angular.js"></script>    <script src="js/scopeAt.js"></script></head><body ng-app="myApp"><div ng-controller="MyCtrl">    <drink flavor="{{ctrlFlavor}}"></drink></div></body></html>
/** * Created by engoo-ypf on 2017/3/6. */var app=angular.module(‘myApp‘,[]);app.controller(‘MyCtrl‘,[‘$scope‘,function ($scope) {    $scope.ctrlFlavor=‘百威‘}])app.directive(‘drink‘,function () {  return{      restrict:‘AE‘,      scope:{          flavor:‘@‘      },      template:‘<div>{{flavor}}</div>‘  }})

=绑定

<!DOCTYPE html><html lang="en"><head>    <meta charset="UTF-8">    <title>Title</title>    <script src="node_modules/angular/angular.js"></script>    <script src="src/js/scopeEqual.js"></script></head><body ng-app="myApp"><div ng-controller="MyCtrl">    指令:    <drink flavor="ctrlFlavor"></drink>    <br>    控制器:    <input type="text" ng-model="ctrlFlavor">    <br></div></body></html>
/** * Created by engoo-ypf on 2017/3/6. */var app=angular.module(‘myApp‘,[]);app.controller(‘MyCtrl‘,[‘$scope‘,function ($scope) {    $scope.ctrlFlavor=‘百威‘}])app.directive(‘drink‘,function () {    return{        restrict:‘AE‘,        scope:{            flavor:‘=‘        },        template:‘<input type="text" ng-model="flavor"/>‘    }})

& 传递一个来自父级scope的函数,稍后调用

<!DOCTYPE html><html lang="en"><head>    <meta charset="UTF-8">    <title>Title</title>    <script src="../node_modules/angular/angular.js"></script>    <script src="js/scopeAnd.js"></script></head><body ng-app="myApp"><div ng-controller="MyCtrl">    <greeting greet="sayHello(name)"></greeting>    <greeting greet="sayHello(name)"></greeting>    <greeting greet="sayHello(name)"></greeting>    <greeting greet="sayHello(name)"></greeting></div></body></html>
/** * Created by yangp on 2017/3/6. */var app=angular.module(‘myApp‘,[]);app.controller(‘MyCtrl‘,[‘$scope‘,function ($scope) {    $scope.sayHello=function (name) {        alert(‘Hello‘+name);    }}]);app.directive(‘greeting‘,function () {    return{        restrict:‘AE‘,        scope:{            greet:‘&‘        },        template:‘<input type="text" ng-model="userName"/><br>‘+        ‘<button ng-click="greet({name:userName})">Greet</button><br>‘    }})

2-8 指令