前言:
前一段时间接触了Angular框架,这是一款非常实用的JS框架,它可以大大减少直接对页面元素的操作,使复杂功能的实现更简单。AngularJS有着诸多特性,最为核心的是:MVW(Model-View-Whatever)、模块化、自动化双向数据绑定、语义化标签、依赖注入等等。想要真正把Angular的优势发挥到极致,还是需要转变传统前端编码思路的,更多的把注意力放在数据模型的设计上,更多的运用一些后台编程思想。废话不多说,直接开始今天的正文。
我项目中使用较多前端UI框架时layui,当初选择layui主要是因为觉得layui使用简单。但是把Angular和layui结合起来使用的话,经常会遇到一些表单元素概率性刷新不出来的情况。究其根本原因无非就是页面元素加载和js代码执行顺序的问题,说白了就是layui的js代码需要根据自己逻辑处理页面元素的时候,但是页面元素还未生成或者加载成功。最常见的场景就是在页面代码使用了ng-repeat,ng-repeat中又有一些需要layui.form.render方法才能刷新出来的元素,这时由于执行render的时机不对就会产生页面元素概率刷新不出来的问题。借此我们引出angular的第一个使用技巧---自定义指令。
Angular自定义指令
js代码片段
app.directive('onFinishRender',['$timeout','$parse',function($timeout,$parse){ return { restrict: 'A', link: function(scope,element,attr){ if(scope.$last === true){ $timeout(function(){ scope.$emit('ngRepeatFinished'); var fun = scope.$eval(attr.onFinishRender); if(fun && typeof(fun) == 'function' ){ fun(); } }); } } } }])页面使用指令片段
<div class="layui-form-item" style="margin-top: 20px"> <label class="layui-form-label" style="width: 90px;text-align: left;padding: 0;line-height: 35px" >请选择:</label> <div class="layui-input-block" style="width: 296px;margin-left: 100px"> <select lay-filter="bindFilter" lay-search=""> <option value="">直接选择或搜索选择</option> <option value={{x.id}} ng-repeat="x in devices" on-finish-render="deviceLoaded" ng-selected="x.id == device.id" >{{x.name}}-{{x.ip}}</option> </select> </div> </div>上面的代码中我们自定义了一个on-finish-render的指令,这个指令能实现这样一个功能:在ng-repeat元素加载完成之后,会产生一个ngReapeatFinished事件,同时on-finish-render属性可以是一个方法名,元素加载完成之后会执行这个方法名对应的方法。我们也可以使用$scope.$on方法来监听ngReapeatFinished事件,以便加入我们的逻辑。实际项目中我们可以使用app的$rootScope来监听此事件,统一执行元素刷新操作。
再聚一个自定义标签的例子
模板代码
<div class="modal-title"> <div class="title-icon"></div> <span>{{title}}</span> <a ng-click="close()"><span class="center_vertical"></span></a> </div>js代码
app.directive('modalTitle', function () { return { restrict: 'EA', templateUrl: 'tpls/modal-title.html', scope:{ title:'@', close:'&' } } } );指令的使用
<modal-title title="我是标题" close="dismissModal()"></modal-title>利用directive的特性,我们还可以做很多事情,在此列出directive的全部属性有兴趣的同学可以挨个属性的用法了解一下。相关的文档很多,在此就不做细说了。
angular.module('myApp', []) .directive('myDirective', function() { return { restrict: String, priority: Number, terminal: Boolean, template: String or Template Function: function(tElement, tAttrs) (...}, templateUrl: String, replace: Boolean or String, scope: Boolean or Object, transclude: Boolean, controller: String or function(scope, element, attrs, transclude, otherInjectables) { ... }, controllerAs: String, require: String, link: function(scope, iElement, iAttrs) { ... }, compile: // 返回一个对象或连接函数,如下所示: function(tElement, tAttrs, transclude) { return { pre: function(scope, iElement, iAttrs, controller) { ... }, post: function(scope, iElement, iAttrs, controller) { ... } } // 或者 return function postLink(...) { ... } } }; });