Angular 应用技巧总结


Posted in Javascript onSeptember 14, 2016

angular的核心思想是通过数据驱动一切,其他东西都是数据的延伸.

套用Javascript一切皆对象的思想,在angular中可以说一切皆数据.

  关于项目构建   

    (1) requirejs以及Yeoman

    在刚开始接触或者使用Angular的时候,总会疑惑与类似的问题,我实践的答案是不需要requirejs或者Yeoman.前者不使用,因为angular本身有module的实现.后者是因为Angular组织结构以及项目构建完全不必要弄得如此繁杂,手写或者在github上pull一个seed项目即可.

    (2) 如何组织项目结构

    这个问题有点废材,因为完全因人因项目而异.个人推荐的是两种组织结构,一种按照代码功能,也就是controller都放在一个文件夹下,services都放在一个文件夹下.另一种则遵循所实现的功能,比如User就把对应的template,services,controller都放在User文件夹下.

    两种都可以,从维护角度上看第二种会更好一些.

    (3) controller以及service的划分

    这里controller通常就是一个页面一个controller,假如一个页面有公共的部分,公共部分永远使用一个controller.对于service要划分成两个部分,一个是于服务器交互数据的service,另一个是一些功能性common的内容,其中放置一些自己写的可复用的服务,类似于notify等.

    至于service要不要按照功能和模块再进一步划分,这个就看项目来了.

    (4) Angular插件以及库的使用

    对于一个项目所有的东西都去网上拿现成的肯定不现实,但是所有的东西都自己写就更不实际了.Angular的很多插件是由Angular团队开发出来或者一些人用jquery插件封装的.我对于插件的观点很简单,如果拿来用赶紧需求可以满足就用,不能满足就自己写或者在已有插件上改进.

    对于如果你调试几个小时还搞不定的插件,听我的劝,放弃它吧.大多数插件都是一些UI插件,大可不必追求繁杂,有时候简简单单的HTML控件也自有它简约的美.

    如果你遇到Angular插件冲突,尤其是UI插件,大多数的情况下要放弃其中之一,比如angular-ui和angular-strap.   

  使用技巧

    下面进入正文,我会列举出我在使用angular的过程中使用的一些技巧,会以场景的形式一一列举.这里对于Angular的一些基础概念我不会解释,本文是一些技巧性的东西,不是基础教程.

    (1) angular中"{{}}"于Python的flask冲突

    Python的flask使用的模板中,数据绑定也是通过两个"{"大括号,这就于angular的数据绑定有冲突.这个有两种解决方法,一种是修改angular的绑定标记,另一种就是修改flask的绑定标记,这里两种方案都给出.

    修改angular:

$interpolateProvider.startSymbol('{[{').endSymbol('}]}');
// 将这句话加在config中即可,放在route的module中即可.这里将原来angular的{{ }}绑定,修改为通过{[{ }]}绑定.   

    修改flask:

class CustomFlask(Flask):
  jinja_options = Flask.jinja_options.copy()
  jinja_options.update(dict(
    block_start_string='{%',
    block_end_string='%}',
    variable_start_string='{#',
    variable_end_string='#}',
    comment_start_string='<#',
    comment_end_string='#>',
  ))
  
app = CustomFlask(__name__, instance_path='/web')

    这里我推荐修改flask,因为用了angular之后,前后端分离.flask的jinjia模板不再需要,同时如果你修改了Angular的绑定标记,其他的控件和库会有问题的.

    (2) 去除url中总是默认带有"#"

    在设置route的时候,开启HTML5模式.

angular.module('router', ['ngRoute'])
.config(['$routeProvider', '$locationProvider',
 function($routeProvider, $locationProvider) {
  $locationProvider.html5Mode(true);  // 设置一下这句即可
 }
]);

    (3) ng-click="expression"以及类似的指令,如何在expression中书写多个表达式?

    比如我在一个ng-click中想要给2个变量赋值,通过";"分号分割即可:

<a ng-click="obja=1;objb=2"></a>

    (4) $watch没有产生作用或者只生效一次

    这种情况一般来说是监听一个字符串或者数字的时候会出现,$scope.$watch("name",function(){}).没有生效或者只生效一次,解决方法是$watch尽量监听的是一个对象,将你要监听的值附在一个Object下即可.

    当你使用angular-ui中的modal时,这个比较明显.具体的原因是因为$scope的继承,因为modal相当于在当前页面的controller中又创建了一个scope,所以对于字面量没法检索追溯原型链,想解决就要有一个对象,才能通过原型链实现跨父子scope的数据刷新绑定.

    (5) 希望ng-view的内容全页面显示

    通常一个页面可能会有固定的top-menu或者sidebar,这类固定不变的部分,然后每次route变化的都是ng-view的template,如果一个页面希望整个页面完全显示它自己,不包括top-menu之类固定的部分.

    这里通常是一个index.html和一个ng-view显示的template.html,top-menu和sidebar位于index.html中,将它们的显示隐藏通过ng-if绑定一个变量控制.

    如果一个页面需要自己完全显示,不显示sidebar等,则在其controller中通过$scope.$emit向上发送一个消息,然后index页面的controller则通过$scope.$on监听消息,一旦听到那个消息,则改变控制sidebar显隐的变量.

    也可以通过service做一个全局的变量控制,个人推荐还是通过消息广播的方式.

    (6) 切记用ng-if代替ng-show

    这是angular的一个小坑,也可以说是不大不小的一个坑.一些长列表数据,可能有一些东西是通过默认隐藏,点击显示的形式展现的.而这部分可控制显隐的内容中也会伴随很多数据绑定.这个在页面渲染的时候非常影响性能.

    举一个列子,比如说通常angular建议一个页面的数据绑定不超过2000个,假如现在有一个页面直接绑定了2000个model,然后你加载,会发现非常卡.如果你将每100的model设置为ng-show,默认情况下不显示,你会发现还是很卡.

    然后你将所有的ng-show换成ng-if,你会发现性能瞬间快的像两个应用.原因在ng-show还是会执行其中的所有绑定,ng-if则会在等于true,也就是显示的时候再去执行其中的绑定.这样一来性能就有很大的提高,我之前通过这个简单的修改,页面加载快了10倍左右.

    所以在能使用ng-if的情况,用它代替所有的ng-show和ng-hide吧.   

    (7) 关于ng-bind-html

    通常情况下为html元素绑定数据,有ng-bind就够了,但一些情境下需要绑定的不是一般的数据,而是html.那么ng-bind就不够用了,需要使用ng-bind-html,它会将内容作为html格式输出.比如想输出带有class的html,那么就使用ng-bind-html,而且还需要ngSanitize的配合,需要引入相应的文件.

    (8) 获取ng-repeat数据filter后的结果

    这个一般在搜索的时候需要用到,比如多重ng-repeat数据形成列表.然后filter一个字段,现在要得到filter之后的结果,有2中方式.

    一种是在html的ng-repeat中类似这么写:

ng-repeat="food in foodCategory._displayfoods = (foodCategory.foods | filter: { 'name': searchobj.foodfilter } | orderBy: food.sort_order)"

   这样_displayfoods就是filter后的最终显示的结果.另一种方式是通过两套数据,一套写在controller中,然后filter以及orderBy都是在controller中操作,最后操作的结果在用来ng-repeat.

    第一种方式比较方便,第二种方式更好,性能也好.

    (9) ng-class以及ng-style通过判断赋值

    根据变量的值决定是否应用某种class,以及不同的style样式.

    ng-class="{'state-error':!foodForm.foodstock.$valid}"

    ng-style="{ color: i.color=='' || i.name=='活' ? 'default' : '#fff' }"

    (10) form校验以input为例

    angular的form可以通过input的HTML5属性进行校验,这里主要通过form以及input的name属性进行锁定,formname.inputname.$valid表示name为inputname的空间是否通过本身的属性校验.

    (11) $resource和$http的$promise

$q.all([
 resource.query().$promise,
 resource2.query().$promise
]).then(functon(success){
 console.log(success);
},functon(error){
 console.log(error);
});
foodFactory.food.save(f).$promise.then(function(result){
 foodFactory.food.get({id:result.id}).$promise.then(function(data){
 });
});

    这个不解释了,直接看就可以了,注意$http的promise需要手动返回,所以一般情况下都通过$resource.

    (12) 仅$watch监听collection中的一个属性

    $watch的第三个参数设置为true,即可deep watch.不过有时候其实不想或者不需要监听collection的全部属性.只要监视其中的一个或者几个,这时候通过for循环虽然可以循环$watch不过明显太挫.

    通过下面这种写法就可以监控一个collection的单独一个object属性.

$scope.people = [
  {
    "groupname": "g1", 
    "persions": [
      {
        "id": 1, 
        "name": "bill"
      }, 
      {
        "id": 2, 
        "name": "bill2"
      }
    ]
  }, 
  {
    "groupname": "g2", 
    "persions": [
      {
        "id": 3, 
        "name": "bill3"
      }, 
      {
        "id": 4, 
        "name": "bill4"
      }
    ]
  }
]

$scope.$watch(function($scope) {
  return $scope.people.map(function(obj) {
    return obj.persions.map(function(g){
      return g.name
    });
  });
}, function (newVal) {
  $scope.count++;
  $scope.msg = 'person name was changed'+ $scope.count;
}, true);

    (13) debounce防抖处理

    这个对于频繁出发的处理非常有用,适用于类似ng-change,$watch的一些场景.比如根绝关键字即时搜索的场合,将$debounce封装为服务,直接调用接口,代码:http://jsfiddle.net/Warspawn/6K7Kd/

    (14) 快速定位到某个位置

    一般来讲页面内通过<a id="bottom"></a>这样的形式就可以结合js代码,实现快速定位.在angular中也是通过类似的原理实现,代码如下:      

var old = $location.hash();
     $location.hash('batchmenu-bottom');
     $anchorScroll();
     $location.hash(old);

    这样写是因为直接location.hash会导致url变化,页面跳转,所以加了防止跳转的代码.

    暂时就总结了这么多,很多东西都是查资料以及自己实践的,希望对需要的TX会有所帮助,以后如果有新的东西会续写一下.

      以上就是对Angular 应用技巧的总结,后续继续添加整理相关文章,谢谢大家对本站的支持!

Javascript 相关文章推荐
javascript 全角转换实现代码
Jul 17 Javascript
基于IE下ul li 互相嵌套时的bug,排查,解决过程以及心得介绍
May 07 Javascript
根据身份证号自动输出相关信息(籍贯,出身日期,性别)
Nov 15 Javascript
jquery.autocomplete修改实现键盘上下键自动填充示例
Nov 19 Javascript
jquery中push()的用法(数组添加元素)
Nov 25 Javascript
JavaScript实现添加、查找、删除元素
Jul 02 Javascript
Vue之Watcher源码解析(2)
Jul 19 Javascript
vue+iview动态渲染表格详解
Mar 19 Javascript
VUE路由动态加载实例代码讲解
Aug 26 Javascript
javascript实现异形滚动轮播
Nov 28 Javascript
基于javascript实现放大镜特效
Dec 03 Javascript
关于vue中如何监听数组变化
Apr 28 Vue.js
AngularJS 所有版本下载地址
Sep 14 #Javascript
JS组件系列之使用HTML标签的data属性初始化JS组件
Sep 14 #Javascript
Angularjs 制作购物车功能实例代码
Sep 14 #Javascript
一步一步封装自己的HtmlHelper组件BootstrapHelper(三)
Sep 14 #Javascript
Angular ng-repeat 对象和数组遍历实例
Sep 14 #Javascript
一步一步封装自己的HtmlHelper组件BootstrapHelper(二)
Sep 14 #Javascript
利用bootstrapValidator验证UEditor
Sep 14 #Javascript
You might like
destoon会员注册提示“数据校验失败(2)”解决方法
2014/06/21 PHP
使用jquery与图片美化checkbox和radio控件的代码(打包下载)
2010/11/11 Javascript
jquery随机展示头像代码
2011/12/21 Javascript
javaScript array(数组)使用字符串作为数组下标的方法
2013/11/19 Javascript
jQuery实现带渐显效果的人物多级关系图代码
2015/10/16 Javascript
浅谈几种常用的JS类定义方法
2016/06/08 Javascript
同步异步动态引入js文件的几种方法总结
2016/09/23 Javascript
jQuery EasyUi 验证功能实例解析
2017/01/06 Javascript
jQuery为某个div加入行样式
2017/06/09 jQuery
JS身份证信息验证正则表达式
2017/06/12 Javascript
js CSS3实现卡牌旋转切换效果
2017/07/04 Javascript
Vue 兄弟组件通信的方法(不使用Vuex)
2017/10/26 Javascript
JS中常用的消息框总结
2018/02/24 Javascript
使用bootstrap实现下拉框搜索功能的实例讲解
2018/08/10 Javascript
编写更好的JavaScript条件式和匹配条件的技巧(小结)
2019/06/27 Javascript
jquery.pager.js分页实现详解
2019/07/29 jQuery
vue中动态select的使用方法示例
2019/10/28 Javascript
通过实例了解JS执行上下文运行原理
2020/06/17 Javascript
微信小程序收藏功能的实现代码
2020/06/19 Javascript
[04:42]2015国际邀请赛CDEC战队晋级之路
2015/08/13 DOTA
[54:10]Spirit vs NB Supermajor小组赛 A组败者组决赛 BO3 第一场 6.2
2018/06/03 DOTA
利用Python绘制数据的瀑布图的教程
2015/04/07 Python
在Python中使用base64模块处理字符编码的教程
2015/04/28 Python
python使用urllib2提交http post请求的方法
2015/05/26 Python
python解析xml文件实例分析
2015/05/27 Python
如何用Python实现简单的Markdown转换器
2018/07/16 Python
详解多线程Django程序耗尽数据库连接的问题
2018/10/08 Python
老生常谈python中的重载
2018/11/11 Python
python自动化测试无法启动谷歌浏览器问题
2019/10/10 Python
音频处理 windows10下python三方库librosa安装教程
2020/06/20 Python
matplotlib交互式数据光标mpldatacursor的实现
2021/02/03 Python
HTML5中原生的右键菜单创建方法
2016/06/28 HTML / CSS
公司周年庆活动方案
2014/08/25 职场文书
毕业生求职自荐信(2016最新版)
2016/01/28 职场文书
Nginx服务器如何设置url链接
2021/03/31 Servers
golang通过递归遍历生成树状结构的操作
2021/04/28 Golang