AngularJS学习

https://www.cnblogs.com/lovesong/p/4870006.html

AngularJS是一个框架,框架决定整个项目的开发套路,以框架为主导。

jQuery是一个函数库,以项目本身为主导。

angularjs是个双向绑定的前端JS框架,其他特性都是围绕它工作的。

它适用于CRUD应用(增加(create)、读取(retrieve)、更新(update)和删除(delete))

双向绑定:

 

                                    (当模板编译视图,视图发生变化触发数据模型变化,数据模型又会作用于视图。)

angularjs元件:其中controller、directive是最为重要的

  

  

   module:

     作为模块组织者,包含其他angularJS元件

   controller:

    负责跟view沟通,不处理任何跟DOM有关的工作

    PS:当你的controller里面写了DOM操作时,就应该反省代码是否写得有问题了。

   directive:

    类似于HTML标签,可以定义标签的行为,所有与DOM相关的操作都应该写在这里。

    PS:尽量不要DOM操作,但可能还是会需要用到,用到时就要在directive里用。

    service:

     写可以独立运作的代码(与view无关),共用于元件(例如控制器)之间,不应该处理任何跟DOM有关的工作。后台数据的请求接口

    filter:

    对数据做一些修理,不应该处理任何跟DOM有关的工作

   config:

    用来定义路由规则,不应该处理任何跟DOM有关的工作

双向数据绑定:

  双向数据绑定是个重要的特性,当view中有数据发生了变化,这个变化会反馈到Model的scope的数据上,而当scope数据发生变化时,view中的数据也会更新到最新的值。

  三个方法:

    scope重要的方法:$apply,$digest,$watch

    1$watch

      注册一个watcher,监听scope的数据,当数据变化时候调用回调函数。第一个参数是被监听的数据,第二个参数是回调函数。

    2$digest

      检查scope中的数据是否发生变化,如果变化则关联到该watcher的回调函数就会被执行。

    3$apply

      这方法是调用$rootScope.$digest(),在$rootScope开始$digest,随后会访问到所有的children scope中的watchers。$apply()方法有两种形式。第一种会接受一个function作为参数,执行该function并且触发一轮$digest循环。第二种会不接受任何参数,只是触发一轮$digest循环。

      PS:angularjs并不直接调用$digest(),而是调用$scope.$apply()

              

    当HTML写下表达式如{{ name }}或ng-model="name"时,angularJS在幕后会为你在scope模型上设置一个watcher,如下:

    

$scope.$watch( 'name' ,function (newValue , oldValue){
     //update the DOM with newValue   
} );

  当页面JS事件触发时,angularJS会监视到并更改scope数据,并自动触发一轮$digest循环,每个关联的watcher的回调函数被执行,最后view被更新。

注意地方

  1.有的时候你发现明明scope的数据已经改了,但你发现view并没有更新。

    这是因为你可能在setTimeout、异步请求等里面去修改数据,但此时angularJS并不知道数据已经变了,不会帮你调用digest循环,所以你需要手动调用$apply。目前一些指令(例:ng-click、ng-model)以及服务(例$timeout、$http)被调用时会自动触发一次$digest循环,这些就不用手动调用$apply.

    

setTimeout( function () { 
   $scope.$apply( function () {
       //wrapped this within $apply
       $scope.name='lu';
    } )    
},2000 )

 

setTimeout( function () {
    $scope.name="lu";
    $scope.$apply();
} ,2000);

  2.脏检查(Dirty checking)

        当一个$direst循环运行时,watchers会被执行来检查scope中的models是否发生了变化,如果发生了变化,那么相应的listener函数就会被执行。在当前的一次循环结束后,它会再执行一次循环用来检查是否有models发生了变化。这就是脏检查(Dirty Checking),它用来处理在listener函数被执行时可能引起的model变化。因此,$digest循环会持续运行直到model不再发生变化,或者$digest循环的次数达到了10次。

  PS:$digest循环最少也会运行两次,即使在listener函数中并没有改变任何model

  3.监控的表达式不要过于复杂,表达式数量不要太多

  4.监听含税内不要有DOM操作,那样会显著降低性能

       5.不能互相监听对方会修改的属性,以免形成交叉引用

 https://www.cnblogs.com/lovesong/p/4889931.html

  angular1.3技巧:

  1.ng-repeat多个字段排序的写法:

    使用orderBy过滤器,第一个参数是一个数组,表示依次按数组中的属性值进行排序(若按第一项比较的值相等,再按第二项比较),第二个参数是正序还是倒序(默认是正序)。

ng-repeat="groupUser in groupUsers | orderBy : ['isOwner' ,'isAdmin'] : true"

  2.ng-include引入HTML片段

    使用ng-include,第一个参数是页面的相对地址的字符串。应该注意,是一个字符串,不是ng-expression,所以不要忘了加单引号,否则会发现怎么都引不进这个HTML片段。

<div ng-include="'msgs.html'"></div>

  3.ng-bind的$scope对象没有随着数据变化而变化

             自己实现的ajax,获取数据后,设置到$scope上,view却没有更新,这其实就是angular双向数据的原因,angular不可预见的scope变化,是不会帮忙刷新view的(例:$.ajax和setTimeout)。解决方法就是,数据设置到$scope上后,手动调用$scope.$apply().

        PS:一些指令(例ng-click、ng-model)以及服务(例:$timeout、$http)才会自动刷新view。

        4.移动触摸(Touch)事件

  angular-touch模块提供了触摸的事件和其他手势ngSwipeLeft、ngSwipeRight。

        5.ng-bind-html的内容无法正常的显示在页面中

       使用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)返回的是受信任的对象。

  6.如何划分一个module

       在关系比较密切(业务逻辑)的页面可以划为一个module,因为页面可能存在公用service或template或directive(controller不共用),而这些元件归属于同个module,我们就可以不同页面调用了。而不相关的页面可划分为另一个module,增加代码的清晰度。

       7.是否要把工具类弄成service

        在弄工程之前,我会考虑到是否要将一些工具类封装成一个service(为了看起来代码统一),但我觉得是没有必要的,因为service是归属于某个模块的,而我们的工具类可能在不同模块都有使用,不归属于某个模块,把工具类当成一个jQuery的库引入即可。

  8.配合RequireJS使用

  angular没有异步加载模块的功能,所以使用配合RequireJS的效果还不错的。在这里面有些异议的是对于模块定义的地方,是该把一个模块定义成RequireJS的模块还是angular的服务(可以依赖注入),我觉得还是功能归属的问题,如果是全局使用的工具服务,就定义成RequireJS模块,而如果是与模块密切相关的业务逻辑就使用服务。

      PS:可在RequireJS的config加上urlArgs,可以避免缓存问题。

urlArgs : "bust="+(new Date()) .getTime()  //可用来清理缓存,在部署到生产环境去掉。

  9.iframe打开跨域URL时报错  

<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/**'
     ]);
});

  10.使用其他Controller的scope的属性方法

        ****原作者声明:

    我并不清楚我的用法是否恰当,使用其他Controller的scope局限于其parent scope,而不是任何Controller的都可以访问。scope有个属性$parent,通过这个属性可以找到某一层controller的scope。    

var parentScope=$scope.$parent.$parent.$parent

          PS:多少层$parent是我打印scope对象找出来的

      11.form表单的自动提交功能

         在输入框点击回车时,angularjs会默认触发第一个button的click事件。

 

 

注意:

  ng-options的value值的类型是number,当list.id是string类型时无法循环。

       ng-repeat的value值的类型是string,当list.id是number类型时无法循环。

    合适的案例:    

  var optItems1 = [{id:1,text:'武汉'},{id:2,text:'北京'},{id:3,text:'杭州'}];
  var optItems2 = [{id:'1',text:'武汉'},{id:'2',text:'北京'},{id:'3',text:'杭州'}];

        

  <select ng-model="query.city" ng-options="x.id as x.text for x in optItems1">
    <option value=""></option>
  </select>

       

  <select ng-model="query.city">
    <option value=""></option>
    <option ng-repeat="x in optItems2" value="{{x.id}}">{{x.text}}</option>
  </select>

  

 

 

 

         

 

posted @ 2019-04-25 17:35  聂小恶  阅读(249)  评论(0编辑  收藏  举报