框架选择。在上一篇文章评论中,有人说angular1.3是个过时的东西,建议使用angular2。其实这种说法很像拿jQuery1.x和jQuery2.x做比较,新的版本当然会有优化优势的地方,但并不一定是最适合你项目的。当你项目必须支持IE6/7/8时,那又得使用jQuery1.x版本。所以不要以新不新去选择一个框架或者某个版本,而是看是不是适合的。当初用angular1.3是他比较成熟有配套的文档,而angular2的文档是不健全的,另外有一点是1.x与2.x的区别太大了,两者的用法没有继承性。更重要的是,目前的angular2只有Alpha版本(测试),并没有一个正式版本。
性能。有人说angular2的性能会比较好,我还没有用过,不做什么评论。但对于angular1.x,我确实是不放心它的性能的,作为PC Web我敢用angular,但在移动终端我不敢用,在我看来无论从框架体积或框架运行效率,在脆弱的移动端都是致命的。有一些基于angular做的Hybrid框架(例Ionic),希望使用过的人能告诉我它体验怎么样(性能上)。
这篇文章记录一些angular1.3的小技巧,angular2我会找个时间做个实践。
使用orderBy过滤器,第一个参数是一个数组,表示依次按数组中的属性值进行排序(若按第一项比较的值相等,再按第二项比较),第二个参数是正序还是倒序(默认是正序)。
ng-repeat="groupUser in groupUsers | orderBy:['isOwner','isAdmin']:true"
使用ng-include,第一个参数是页面的相对地址的字符串。应该注意,是一个字符串,不是ng-expression,所以不要忘了加单引号,否则会发现怎么都引不进这个HTML片段。
<div ng-include="'msgs.html'"></div>
自己实现的ajax,获取数据后,设置到$scope上,view却没有更新。这其实就是angular双向数据的原因,angular不可预见的scope变化,是不会帮忙刷新view的(例$.ajax或setTimeout)。解决方法就是,数据设置到$scope上后,手动调$scope.$apply();。
PS:一些指令(例ng-click、ng-model)以及服务(例$timeout、$http)才会自动刷新view。
angular-touch模块提供了触摸的事件和其他手势ngSwipeLeft、ngSwipeRight。
使用ng-bind-html属性,该属性依赖于$sanitize,也就是需要引入angular-sanitize.js文件。但会发现ng-bind-html的内容无法正常的显示在页面中,这是因为某些标签会被angularJS认为是不安全的自动过滤掉,而为了保留这些表情就需要开启非安全模式。
<div ng-bind-html="article.content | trustHtml"> </div>
myApp.filter('trustHtml', function ($sce) { return function (input) { return $sce.trustAsHtml(input); } });
其中$sce是angular自带的安全处理服务,$sce.trustAsHtml(input) 返回的是受信任的对象。
我的想法是在关系比较密切(业务逻辑)的页面可以划为一个module,因为页面可能存在共用service或template或directive(controller不共用),而这些元件归属于同个module,我们就可以不同页面调用了。而不想关的页面可划分为另一个module,增加代码的清晰度。
在弄工程之前,我会考虑到是否要将一些工具类封装成一个service(为了看起来代码统一),但我发觉是没有必要的,因为service是归属于某个模块的,而我们的工具类可能在不同模块都有使用,不归属于某个模块。把工具类当成一个jquery的库引入即可。
angular没有异步加载模块的功能,所以使用配合RequireJS使用的效果还是不错的。在这里面有些异议的是对于模块定义的地方,是该把一个模块定义成RequireJS的模块还是angular的服务(可以依赖注入),我觉得还是功能归属的问题,如果是全局使用的工具服务,就定义成RequireJS模块,而如果是与模块密切相关的业务逻辑就使用服务。
PS:可在RequireJS的config加上urlArgs,可以避免缓存问题。
urlArgs: "bust=" + (new Date()).getTime() //可用来清理缓存,在部署到生产环境去掉。
<iframe width="100%" height="100%" ng-src="{{url}}"></iframe>
如果不做处理,上面的跨域URL是打不开的, 需要定义白名单。
myApp.config(function($sceDelegateProvider) { $sceDelegateProvider.resourceUrlWhitelist([ // Allow same origin resource loads. 'self', // Allow loading from our assets domain. Notice the difference between * and **. "https://link.bingosoft.net/**"]); });
先声明我并不清楚我的用法是否恰当。使用其他Controller的scope局限于其parent scope,而不是任何Controller的都可以访问。scope有个属性$parent, 通过这个属性可以找到某一层Controller的scope。
var parentScope = $scope.$parent.$parent.$parent;
PS:多少层$parent是我打印scope对象出来找的。