改善用户体验的3个AngularJS指令

开发 前端
AngularJS指令可以为给你的访问者提供更好的用户体验,比如通过展示用户头像来使页面看起来更具个性化。在你的注册表单中,可以在电子邮箱地址一栏的旁边展示一个头像,指示用户输入的是否是一个正确的邮件地址……

AngularJS指令可以为给你的访问者提供更好的用户体验,比如通过展示用户头像来使页面看起来更具个性化。在你的注册表单中,可以在电子邮箱地址一栏的旁边展示一个头像,指示用户输入的是否是一个正确的邮件地址。如果在你的表单中有可选输入项,你可以默认隐藏它们,当用户点击时再展示出来,并且立刻自动将焦点对准第一个输入框。这些方法非常容易实现,并且可以通过指令来获得复用。

你有许多方式来构建AngularJS指令。关于如果创建用户指令已经有非常多的教程和指导(所以我不打算在此描述一些基本的东西):

我这里选取了三条对于提升用户体验非常有帮助的指令,并且我很早就将其应用在产品中。

1.头像图片

为了在你的应用中展示头像图片,你需要使用用户的电子邮件地址,将地址转换为小写并使用md5加密该字符串。所以聪明的做法是使用指令来做到这些,并且可以复用。

  1. /*  
  2.  * A simple Gravatar Directive  
  3.  * @example  
  4.  *   <gravatar-image email="test@email.com" size="50"></gravatar-image>  
  5.  */ 
  6. app.directive('gravatarImage'function () {  
  7.   return {  
  8.     restrict: 'AE',  
  9.     replace: true,  
  10.     required: 'email',  
  11.     template: '<img ng-src="https://www.gravatar.com/avatar/{{hash}}?s={{size}}&d=identicon" />',  
  12.     link: function (scope, element, attrs) {  
  13.       attrs.$observe('email'function (value) {  
  14.         if(!value) { return; }  
  15.    
  16.         // MD5 (Message-Digest Algorithm) by WebToolkit  
  17.         var md5=function(s){function L(k,d){return(k<<d)|(k>>>(32-d));}function K(G,k){var I,d,F,H,x;F=(G&2147483648);H=(k&2147483648);I=(G&1073741824);d=(k&1073741824);x=(G&1073741823)+(k&1073741823);if(I&d){return(x^2147483648^F^H);}if(I|d){if(x&1073741824){return(x^3221225472^F^H);}else{return(x^1073741824^F^H);}}else{return(x^F^H);}}function r(d,F,k){return(d&F)|((~d)&k);}function q(d,F,k){return(d&k)|(F&(~k));}function p(d,F,k){return(d^F^k);}function n(d,F,k){return(F^(d|(~k)));}function u(G,F,aa,Z,k,H,I){G=K(G,K(K(r(F,aa,Z),k),I));return K(L(G,H),F);}function f(G,F,aa,Z,k,H,I){G=K(G,K(K(q(F,aa,Z),k),I));return K(L(G,H),F);}function D(G,F,aa,Z,k,H,I){G=K(G,K(K(p(F,aa,Z),k),I));return K(L(G,H),F);}function t(G,F,aa,Z,k,H,I){G=K(G,K(K(n(F,aa,Z),k),I));return K(L(G,H),F);}function e(G){var Z;var F=G.length;var x=F+8;var k=(x-(x%64))/64;var I=(k+1)*16;var aa=Array(I-1);var d=0;var H=0;while(H<F){Z=(H-(H%4))/4;d=(H%4)*8;aa[Z]=(aa[Z]|(G.charCodeAt(H)<<d));H++;}Z=(H-(H%4))/4;d=(H%4)*8;aa[Z]=aa[Z]|(128<<d);aa[I-2]=F<<3;aa[I-1]=F>>>29;return aa;}function B(x){var k="",F="",G,d;for(d=0;d<=3;d++){G=(x>>>(d*8))&255;F="0"+G.toString(16);k=k+F.substr(F.length-2,2);}return k;}function J(k){k=k.replace(/rn/g,"n");var d="";for(var F=0;F<k.length;F++){var x=k.charCodeAt(F);if(x<128){d+=String.fromCharCode(x);}else{if((x>127)&&(x<2048)){d+=String.fromCharCode((x>>6)|192);d+=String.fromCharCode((x&63)|128);}else{d+=String.fromCharCode((x>>12)|224);d+=String.fromCharCode(((x>>6)&63)|128);d+=String.fromCharCode((x&63)|128);}}}return d;}var C=Array();var P,h,E,v,g,Y,X,W,V;var S=7,Q=12,N=17,M=22;var A=5,z=9,y=14,w=20;var o=4,m=11,l=16,j=23;var U=6,T=10,R=15,O=21;s=J(s);C=e(s);Y=1732584193;X=4023233417;W=2562383102;V=271733878;for(P=0;P<C.length;P+=16){h=Y;E=X;v=W;g=V;Y=u(Y,X,W,V,C[P+0],S,3614090360);V=u(V,Y,X,W,C[P+1],Q,3905402710);W=u(W,V,Y,X,C[P+2],N,606105819);X=u(X,W,V,Y,C[P+3],M,3250441966);Y=u(Y,X,W,V,C[P+4],S,4118548399);V=u(V,Y,X,W,C[P+5],Q,1200080426);W=u(W,V,Y,X,C[P+6],N,2821735955);X=u(X,W,V,Y,C[P+7],M,4249261313);Y=u(Y,X,W,V,C[P+8],S,1770035416);V=u(V,Y,X,W,C[P+9],Q,2336552879);W=u(W,V,Y,X,C[P+10],N,4294925233);X=u(X,W,V,Y,C[P+11],M,2304563134);Y=u(Y,X,W,V,C[P+12],S,1804603682);V=u(V,Y,X,W,C[P+13],Q,4254626195);W=u(W,V,Y,X,C[P+14],N,2792965006);X=u(X,W,V,Y,C[P+15],M,1236535329);Y=f(Y,X,W,V,C[P+1],A,4129170786);V=f(V,Y,X,W,C[P+6],z,3225465664);W=f(W,V,Y,X,C[P+11],y,643717713);X=f(X,W,V,Y,C[P+0],w,3921069994);Y=f(Y,X,W,V,C[P+5],A,3593408605);V=f(V,Y,X,W,C[P+10],z,38016083);W=f(W,V,Y,X,C[P+15],y,3634488961);X=f(X,W,V,Y,C[P+4],w,3889429448);Y=f(Y,X,W,V,C[P+9],A,568446438);V=f(V,Y,X,W,C[P+14],z,3275163606);W=f(W,V,Y,X,C[P+3],y,4107603335);X=f(X,W,V,Y,C[P+8],w,1163531501);Y=f(Y,X,W,V,C[P+13],A,2850285829);V=f(V,Y,X,W,C[P+2],z,4243563512);W=f(W,V,Y,X,C[P+7],y,1735328473);X=f(X,W,V,Y,C[P+12],w,2368359562);Y=D(Y,X,W,V,C[P+5],o,4294588738);V=D(V,Y,X,W,C[P+8],m,2272392833);W=D(W,V,Y,X,C[P+11],l,1839030562);X=D(X,W,V,Y,C[P+14],j,4259657740);Y=D(Y,X,W,V,C[P+1],o,2763975236);V=D(V,Y,X,W,C[P+4],m,1272893353);W=D(W,V,Y,X,C[P+7],l,4139469664);X=D(X,W,V,Y,C[P+10],j,3200236656);Y=D(Y,X,W,V,C[P+13],o,681279174);V=D(V,Y,X,W,C[P+0],m,3936430074);W=D(W,V,Y,X,C[P+3],l,3572445317);X=D(X,W,V,Y,C[P+6],j,76029189);Y=D(Y,X,W,V,C[P+9],o,3654602809);V=D(V,Y,X,W,C[P+12],m,3873151461);W=D(W,V,Y,X,C[P+15],l,530742520);X=D(X,W,V,Y,C[P+2],j,3299628645);Y=t(Y,X,W,V,C[P+0],U,4096336452);V=t(V,Y,X,W,C[P+7],T,1126891415);W=t(W,V,Y,X,C[P+14],R,2878612391);X=t(X,W,V,Y,C[P+5],O,4237533241);Y=t(Y,X,W,V,C[P+12],U,1700485571);V=t(V,Y,X,W,C[P+3],T,2399980690);W=t(W,V,Y,X,C[P+10],R,4293915773);X=t(X,W,V,Y,C[P+1],O,2240044497);Y=t(Y,X,W,V,C[P+8],U,1873313359);V=t(V,Y,X,W,C[P+15],T,4264355552);W=t(W,V,Y,X,C[P+6],R,2734768916);X=t(X,W,V,Y,C[P+13],O,1309151649);Y=t(Y,X,W,V,C[P+4],U,4149444226);V=t(V,Y,X,W,C[P+11],T,3174756917);W=t(W,V,Y,X,C[P+2],R,718787259);X=t(X,W,V,Y,C[P+9],O,3951481745);Y=K(Y,h);X=K(X,E);W=K(W,v);V=K(V,g);}var i=B(Y)+B(X)+B(W)+B(V);return i.toLowerCase();};  
  18.    
  19.         scope.hash = md5(value.toLowerCase());  
  20.         scope.size = attrs.size;  
  21.    
  22.         if(angular.isUndefined(scope.size)) {  
  23.           scope.size = 60; // default to 60 pixels  
  24.         }  
  25.       });  
  26.     }  
  27.   };  
  28. });  
  29. 2. Focus-Me  
  30.    
  31. It is really just a small directive, but it’s awesome. In the example below the user clicks on a link, where he makes an input visible, which gets automatically focused. So he doesn’t need to click in the input field when it shows up.  
  32. /**  
  33.  * Sets focus to this element if the value of focus-me is true.  
  34.  * @example  
  35.  *  <a ng-click="addName=true">add name</a>  
  36.  *  <input ng-show="addName" type="text" ng-model="name" focus-me="{{addName}}" />  
  37.  */ 
  38. app.directive('focusMe', ['$timeout'function($timeout) {  
  39.   return {  
  40.     scope: { trigger: '@focusMe' },  
  41.     link: function(scope, element) {  
  42.       scope.$watch('trigger'function(value) {  
  43.         if(value === "true") {  
  44.           $timeout(function() {  
  45.             element[0].focus();  
  46.           });  
  47.         }  
  48.       });  
  49.     }  
  50.   };  
  51. }]); 

2. 关注我

这其实是一个非常简短的指令,但是非常棒。在下面的例子中,用户点击了一个链接,显示的输入框需要能够自动获得焦点。这样,用户在页面显示时不必再手动点击文本域。

  1. /**  
  2.  * Sets focus to this element if the value of focus-me is true.  
  3.  * @example  
  4.  *  <a ng-click="addName=true">add name</a>  
  5.  *  <input ng-show="addName" type="text" ng-model="name" focus-me="{{addName}}" />  
  6.  */ 
  7. app.directive('focusMe', ['$timeout'function($timeout) {  
  8.   return {  
  9.     scope: { trigger: '@focusMe' },  
  10.     link: function(scope, element) {  
  11.       scope.$watch('trigger'function(value) {  
  12.         if(value === "true") {  
  13.           $timeout(function() {  
  14.             element[0].focus();  
  15.           });  
  16.         }  
  17.       });  
  18.     }  
  19.   };  
  20. }]); 

3.Contenteditable元素模型绑定

我们使用contenteditable而不是textarea元素的最主要原因在于使用前者可以在布局和UI中没有限制。我们在编辑器中使用这条指令可以实现将contenteditable元素的html和ng-model进行一个双向绑定。目前,在contenteditable元素中并没有支持ng-model。

  1. /**  
  2.  * Two-way data binding for contenteditable elements with ng-model.  
  3.  * @example  
  4.  *   <p contenteditable="true" ng-model="text"></p>  
  5.  */ 
  6. app.directive('contenteditable'function() {  
  7.   return {  
  8.     require: '?ngModel',  
  9.     link: function(scope, element, attrs, ctrl) {  
  10.    
  11.       // Do nothing if this is not bound to a model  
  12.       if (!ctrl) { return; }  
  13.    
  14.       // Checks for updates (input or pressing ENTER)  
  15.       // view -> model  
  16.       element.bind('input enterKey'function() {  
  17.         var rerender = false;  
  18.         var html = element.html();  
  19.    
  20.         if (attrs.noLineBreaks) {  
  21.           html = html.replace(/<div>/g, '').replace(/<br>/g, '').replace(/<\/div>/g, '');  
  22.           rerender = true;  
  23.         }  
  24.    
  25.         scope.$apply(function() {  
  26.           ctrl.$setViewValue(html);  
  27.           if(rerender) {  
  28.             ctrl.$render();  
  29.           }  
  30.         });  
  31.       });  
  32.    
  33.       element.keyup(function(e){  
  34.         if(e.keyCode === 13){  
  35.           element.trigger('enterKey');  
  36.         }  
  37.       });  
  38.    
  39.       // model -> view  
  40.       ctrl.$render = function() {  
  41.         element.html(ctrl.$viewValue);  
  42.       };  
  43.    
  44.       // load init value from DOM  
  45.       ctrl.$render();  
  46.     }  
  47.   };  
  48. }); 

结论:AngularJS指令可用于改善用户体验

我希望经过文中的介绍,你会感悟到AngularJS指令的有用之处。

对我而言,指令是AngularJS中最激动人心的特性。创建可重用的组件,并可以将其添加到纯粹的HTML应用程序库,这是多么难以置信并且强大的功能。由于指令实用,并且大部分指令书写难度不高,许多开发者早已对于目前受欢迎的库开发了许多指令。举例来说,AngularJS团队已经为Bootstrap创建了一系列的指令(难道还有人不用它吗?),被称作UI Bootstrap

英文:Improve user experience with these 3 AngularJS directives

译文:http://www.oschina.net/translate/better-ux-with-angularjs-directives

责任编辑:林师授 来源: 开源中国社区 编译
相关推荐

2018-09-25 05:06:00

物联网户体验IOT

2011-05-16 14:20:42

jQuery插件

2010-05-18 10:09:38

前端优化

2009-08-12 10:38:09

SilverlightOffice 2010

2009-12-25 09:36:22

惠普电信行业

2009-12-25 18:14:06

惠普实时策略电信

2015-04-13 15:00:29

IBM云计算

2020-10-09 10:15:08

设计UI技巧

2020-12-28 09:35:51

Windows10操作系统微软

2022-06-24 15:22:27

物联网人工智能

2013-07-09 13:29:36

iOS7WWDC苹果

2016-07-01 12:58:56

云计算

2018-11-26 08:23:36

物联网客户体验IOT

2014-10-09 12:50:04

蓝色云用户体验

2023-08-31 08:28:32

软件窗口TTN_SHOW

2015-02-12 16:53:06

手机克隆EMUIiOS

2014-03-12 10:22:59

AngularJS指令

2022-01-30 09:07:21

Firefox火狐浏览器浏览器

2012-08-10 09:24:00

虚拟化

2022-02-09 08:49:37

架构
点赞
收藏

51CTO技术栈公众号