angular指令学习(三)--自定义指令之compile、link的学习

周一到了,哈哈哈,周末在家看了会angular,今天都已经周三了,决定整理下所学所看,主要是指令中的compile和link的学习

先上个例子:

<!DOCTYPE html>
<html ng-app='MyApp'>
<meta  charset="utf-8" />
    <head>
       <script type="text/javascript" src='https://code.angularjs.org/1.5.10/angular.min.js'></script>
        <script type="text/javascript">
var app=angular.module('MyApp',[]);


app.controller('testC',function($scope){
$scope.title='angular学习';
$scope.text='whatever you want to say';
});

app.directive('repeater', function($document) {
    return {
        restrict: 'A',
        compile: function(element, attrs) {
		
            var template = element.children().clone();
            for(var i=0; i<attrs.repeater - 1; i++) {
                element.append(template.clone());
            }
			
        },
		link: function(scope, elem, attrs) {
		
      },
		
   }
});

</script>
</head>
<body>
<div ng-controller='testC'>
<div>

<ul repeater=5>
    <li>caicai</li>
</ul>

</div>
</div>
</body>
</html>
所有的指令的结构其实都大同小异,而我们平时见得大多数是只带link的,那么这个compile和Link到底是干嘛的呢

我们先来看看这个ng是怎样处理指令 的呢

当浏览所以器渲染一个页面时候,本质上是读取html标志,然后建立dom节点,生成dom树,当dom树创建完成后,会广播一个事件给我们,当我们在页面中使用scrrpt标签加载ng应用程序代码时候,ng监听上面的dom完成事件查找带有ng-app属性的元素。当找到这样的元素后,ng开始处理dom这个元素的起点,所以假如ng-app被添加到html元素中,则ng就会从html元素开始处理dom.从这个起点开始,ng开始递归查找所有子元素里面,已经定义好的符合程序的指令,ng怎么处理指令其实是依赖于它定义时的对象属性的,你可以自己定义一个compile或者link函数,或者用pre-link和post-link函数来代替link。简单而言按照字面理解就是编译的意思,像复制元素等都可以在compile中完成,link函数就是完成指令中中的一些与DOM的操作,如注册事件监听、监听模型、以及更新DOM 等。

compile函数

compile函数在link函数被执行之前用来做一些DOM改造,它接受下面参数

tElement-指令所在元素

attrs元素赋予的参数的标准化列表

app.directive('test', function() {
  return {
    compile: function(tElem,attrs) {
      //do optional DOM transformation here
      return {
	        pre: function(scope, iElem, iAttrs,controller){
              },
              post: function(scope, iElem, iAttrs,controller){
              }
return function postLink(){}
	  
};
    }
  };
});

举个例子:

<!DOCTYPE html>
<html ng-app='MyApp'>
<meta  charset="utf-8" />
    <head>
       <script type="text/javascript" src='https://code.angularjs.org/1.5.10/angular.min.js'></script>
        <script type="text/javascript">
var app=angular.module('MyApp',[]);


app.controller('testC',function($scope){
$scope.title='angular学习';
$scope.text='whatever you want to say';
});

app.directive('repeater', function($document) {
    return {
        restrict: 'A',
        compile: function(element, attrs) {
		
            var template = element.children().clone();
            for(var i=0; i<attrs.repeater - 1; i++) {
                element.append(template.clone());
            }
			
        },
		link: function(scope, elem, attrs) {
		
      },
		
   }
});

</script>
</head>
<body>
<div ng-controller='testC'>
<div>

<ul repeater=5>
    <li>caicai</li>
</ul>

</div>
</div>
</body>
</html>

输出结果:


看吧,这大概就是ng-repeat的实现,哈哈,可能你会奇怪了,哎,这个为什么没有pre postlink postlink呢,而是把link单独写在外面,其实compile中的postlink就是link函数,但是很多时候我们都不这么写,因为很多时候我们都不用compile函数,如果你想更深层次的研究pre post的话,可以继续看下去,我在后面写了这个,现在我们暂时放下compile,来看下link函数

 link: function ($scope, $element, $attrs, ctrl) {
                    //获取teacher指令控制器,并调用其方法sayName()
                    $scope.teacherName = ctrl.sayName();
                }

在link阶段要执行的函数,这个属性只有在compile属性没有设置时候才能生效

常用参数为scope element attr 分别为当前元素师的scope  dom元素和元素上的属性,


举个例子:

<!DOCTYPE html>
<html ng-app='MyApp'>
<meta  charset="utf-8" />
    <head>
       <script type="text/javascript" src='https://code.angularjs.org/1.5.10/angular.min.js'></script>
        <script type="text/javascript">
var app=angular.module('MyApp',[]);


app.controller('testC',function($scope){
$scope.clickme=function(){
alert();
}
   $scope.checkUsername = function() {
        //send ajax to check on server
        if ($scope.username === 'hellobug') {
           $scope.usernameAlreadyExist = true;
        }
    }
$scope.title='angular学习';
$scope.text='whatever you want to say';
});


app.directive('ngSelf', function($document) {
    return {
        link: function(scope, element, attrs) {
            element.bind('click', function(e){
                scope.$apply(attrs.ngSelf);
            });
        }
    }
})


</script>
</head>
<body>
<div ng-controller='testC'>
<div>

   
	<button ng-self='clickme()'> click me</button>

</div>
</div>
</body>
</html>

当我们点击button时候,就会发现有alert弹出框

好了,我们综合下angular的指令到底是如何编译的:

前面已经说过了,当页面来到时候,浏览器API先将html转化为dom,然后通知大家dom加载完成,接着angular开始使用$compile服务遍历DOM元素,一旦所有的指令都被识别后,就执行他们的compile方法,compile方法返回一个link函数,被添加到稍后的link函数中,这被称为编译,如果一个指令需要被克隆很多次,compile只会在编译阶段被执行一次,复制这些模板,但是link函数会针对每个被复制的实例去执行,这也说明了为什么在compile函数中不能访问到scope对象,在编译阶段之后,就开始链接阶段,在这个阶段所有收集的link函数将被一一执行,指令创造出的模板会在正确的scope下被解析和处理,然后返回具有事件响应的真实的DOM节点

compile和link的使用时机

想在dom渲染前对其进行变形,并且不需要scope参数,返回值就是link的function

link

对特定元素注册事件

需要到scope参数来实现元素的一些行为

可能有时候我们还会见到这种情况:

下面是拷贝来的,真实性还未测试

使用controller的Directive
页面大致是:
<with-controller datasource="customers" add="addCustomer"></with-controller>
Directive方面:

(function(){
    var withController = function(){
        var template = '<button ng-click="addItem()">Add Item</button><ul>' + '<li ng-repeat="item in items">{{::item.name}}</li></ul>',
        
        controller = ['$scope', function($scope){
            init();
            
            function init(){
                $scope.items = angular.copy($scope.datasource);
            }
            
            $scope.addItem = function(){
                var name = "customer new";
                $scope.add()(name);
                $scope.items.push({
                    name: name
                });
            }
        }];
        
        return {
            restrict: 'EA',
            scope: {
                datasource: '=',
                add:'&'
            },
            controller: controller,
            template:template
        }
    };
    
    angular.module('directiveModule')
        .direcitve('withController', withController);
}());


可见,link和controller的相同点在于里面都可包含数据源和操作。不同点在于:link能控制渲染html元素的过程,而controller不能,controller的模版写死的,仅侧重于提供数据源和操作






评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值