怎么将分页封装成指令?

小课堂-js-task9

分享人:陈杰超

目录

1.背景介绍

2.知识剖析

3.常见问题

4.解决方案

5.编码实战

6.扩展思考

7.更多讨论

8.参考文献

1.背景介绍

对于指令,可以把它简单的理解成在特定DOM元素上运行的函数,指令可以扩展这个元素的功能。 例如,一些原生的指令如 ng-disabled , ng-if ,ng-repeat ,ng-click 等。ng-click可以让一个元素能够监听click事件,并在接收到事件的时候执行AngularJS表 达式。正是指令使得AngularJS这个框架变得强大,并且在AngularJs我们可以自己通过directive来创造新的指令。

2.知识剖析

当在我们的项目中需要实现一些功能,比如,时间筛选、分页的功能,我们最先想到的可能是先去网上找找看,有没有相应的插件可以给我们直接拿来使用。但是插件代码一般十分复杂,无法定位bug进行修改,也无法保证修改后不会出现别的bug,用起来可能不太顺手。像一些实现简单功能的插件,我们可以利用AngularJS中的directive自己写一个指令,进行封装,也可以方便以后重复使用。

3.常见问题

怎么将分页封装成指令?

4.解决方案

先了解一下directive自定义指令中都可以设置哪些选项?

                    
                        app.directive('pagination', function() {
                        return {
                            restrict: String,
                            priority: Number,
                            terminal: Boolean,
                            template:string or Template Function
                            templateUrl: String,
                            replace: Boolean,
                            scope: Boolean or Object,
                            transclude: Boolean,
                            controller: String or function() { ... },
                            controllerAs: String,
                            require: String,
                            link: function() { ... },
                            compile: function() { ... }
                        });
                    
                

restrict: String,

可选字符串参数,可以设置这个指令在DOM中可以何种形式被声明,默认为A(属性)
设置为“E”(标签)
设置为"C"(类名)
M(注释) <--directive:my-directive expression-->

priority: Number
优先级,可忽略,默认为0, ngRepeat的优先级为1000,这样就可以保证在同一元素上,它总是在其他指令之前被调用。
terminal:boolean
默认为false,如果为true则停止运行当前元素上比本指令优先级更低的指令,优先级相同的指令还是会被执行。
template:string or Template Function
指令中重要的属性,必须设置如下一种
1.一段html文本
2.可以接受两个参数的函数
模板中必须只有一个根标签。
当html过长时,可以设置templateUrl引用
templateUrl: String
接受一个路径的字符串,还可以在script标签中写模板。
replace: Boolean,
默认为false(模板内容会加载到标签内部),true(模板内容会替换当前标签)
transclude: Boolean
是否使用ng-transculde来包含html中原有的内容,接收两个参数true/false。默认为false
如果指令使用了 transclude 参数,那么在指令里的控制器中就无法正常监听数据模型的变化了
scope: Boolean or Object
默认为false。直接使用父scope,比较危险。
设置为true,继承父scope
设置为对象,创建一个新的隔离的scope,仍然可以与父scope通信
对象中可设置的绑定方式有三种:
1.@ 单向绑定,外部scope能影响内部scope,但反过来不成立
2.= 双向绑定,外部scope和内部scope的model能够互相改变
3.& 在父scope的上下文中执行一个表达式。此表达式可以是一个function
controller: String or function(scope, element, attrs, transclude, otherInjectables) { ... }
注册在应用中的控制器的构造函数
一般是写为呈现视图之前而准备的数据或者是与其他指令进行数据交互而暴露这个api
controllerAs: String
这个选项是用来设置控制器的别名的

require: String
通俗的说是用于指令之间的相互交流.字符串代表另外一个指令的名字
require会将控制器注入到其值所指定的指令中,并作为当前指令的链接函数的第四个参数。
如果不使用 ^ 前缀,指令只会在自身的元素上查找控制器
使用 ^ 如果添加了 ^ 前缀,指令会在上游的指令链中查找 require 参数所指定的控制器
使用 ? 如果在当前指令中没有找到所需要的控制器,会将 null 作为传给 link 函数的第四个参数
使用 ^? 将前面两个选项的行为组合起来,我们可选择地加载需要的指令并在父指令链中进行查找
                            
                                    var app = angular.modeule('myapp',[]);  
              
                                    app.directive('common',function(){  
                                        return {  
                                        ...  
                                        controller: function($scope){  
                                            this.method1 = function(){  
                                            };  
                                            this.method2 = function(){  
                                            };  
                                        },  
                                        ...  
                                        }  
                                    });  
                                      
                                    app.directive('d1',function(){  
                                        return {  
                                        ...  
                                        require: '?^common',  
                                        link: function(scope,elem,attrs,common){  
                                            scope.method1 = common.method1;  
                                            ..  
                                            },  
                                        ...  
                                        }  
                                    })  
                                
                    
link: function(scope, iElement, iAttrs) { ... }
用 link 函数创建可以操作DOM的指令,比较常用
                        
                                compile: function(tElement, tAttrs, transclude) {  
                                    return {
                                        pre: function(scope, iElement, iAttrs, controller) { ... },
                                        post: function(scope, iElement, iAttrs, controller) { ... }
                                    }
                                    // 或者
                                    return function postLink(...) { ... }
                                }
                            };
                        
                    
设置compile函数的意义在于:在指令和实时数据被放到DOM中之前修改DOM

compile 和 link 选项是互斥的。如果同时设置了这两个选项,那么会把 compile所返回的函数当作链接函数,而 link 选项本身则会被忽略。
通常情况下,如果设置了 compile 函数,说明我们希望在指令和实时数据被放到DOM中之前进行DOM操作,在这个函数中进行诸如添加和删除节点等DOM操作是安全的

5.编码实战

6.扩展思考

分页功能还可以怎么做?

7.更多讨论

1.还可以用directive自定义指令封装哪些插件

2.directive自定义指令中的scope作用和注意点

8.参考文献

参考一: AngularJS权威教程

参考二: Angular简易分页设计

参考三: angular 自定义指令详解 Directive

鸣谢

感谢大家观看

by陈杰超

Contact GitHub API Training Shop Blog About © 2016 GitHub, Inc. Terms Privacy Security Status He