angular js自学笔记(二)——作用域1.0

来源:互联网 发布:qq邮箱更改域名 编辑:程序博客网 时间:2024/06/08 04:42

作用域1.0

控制器与$scope


   了解作用域,首先要理解angular js的控制器。控制器的主要职责是初始化作用域实例,那么问题来了,什么是作用域实例呢?学过Java的人都知道,Java中可以将很多方法和需要的属性封装到一个类中,方便其他类调用,在我个人看来,angular js里面就定义了一个scope类,而我们在html里面使用ng-controller标签(这个标签是由指令(Directives)定义的)时,会自动创建一个scope类的实例。这里就从angular js的运行来谈,由于我之前的学习时针对的Java和c语言,所以就拿Java来做对比,在dom加载完后,浏览器发现ng-app标签后,会先创建一个根作用域$root(这个root可以看成是Java中的类继承的根类),然后看到了ng-controller,于是又创建一个$scope(此时的$scope完全继承自$root,也就是说可以用$root的所有属性),也就是说在一个标签内的另一个标签如果创建作用域,如果没指明父作用域,那么它们之间就有个继承关系,说到这里,再回到控制器来,它的职责有个亮点“初始化”,也就是说控制器其实就是用来给$scope的属性赋值(这里的值可为数组,对象等,这个是js特有的特点)和方法

ng-repeat怎么创建作用域

        ng-repeat我在第一次接触时就喜欢上了它,因为有了它,我可以很简单的实现很多想法,它的作用是重复创建所在的标签,这个时候问题又来了,它这个语法"XXX in XXXs"(后面那个就表示复数啊)按照我上面说的原则,对应每个XXX,都有个新变量要暴露给$scope,而又不能覆盖之前的变量值,这个时候同名(XXX)的属性怎么创建作用域(属性也有自己的作用域,因为js的特点,属性也可以为对象等),angular js为了解决这个问题,使用了一个叫“模型值”(model values)的东东,用以辨别同名的属性作用域(也就是3个数字,如001)。



尝试

        对于以上的学习,我做了如下的尝试来验证:

        test.html

[html] view plaincopy
  1. <span style="font-size:18px;"><html >  
  2. <head>  
  3.     <script type="text/javascript" src="angular.min.js"></script>  
  4.     <script type="text/javascript" src="test.js"></script>  
  5.     <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />  
  6. </head>  
  7. <body ng-app ng-init="appName='app'">  
  8.     $root.appName={{appName}}  
  9.     <div ng-controller="aCtrl">  
  10.         <hr>  
  11.         控制器作用域<br>  
  12.         使用父作用域的appName:<input ng-model="appName">  
  13.         $root.appName:{{appName}}  
  14.           
  15.     <br/>对names进行ng-repeat,给集合每个元素创建一个叫a的属性作用域  
  16.       <div ng-repeat="a in names">  
  17.         <br/>  
  18.         使用a获取:{{a}}<br/>  
  19.         使用a.name获取:{{a.name}}<br>  
  20.       </div>  
  21.     </div>  
  22. </body>  
  23. </html></span>  
        test.js
[javascript] view plaincopy
  1. <span style="font-size:18px;">var aCtrl = function($scope){  
  2.     $scope.names = [  
  3.         {name:"1"},  
  4.         {name:"2"},  
  5.     ];  
  6. };</span>  
       现在来看看浏览器的效果

   

       

        下面是ng-app($root)的作用域,  可以看到我定义的属性appName。

     

        再来看ng-controller($scope)的作用域,它里面也可以看到$root的appName,而且多了个属性names(这是我通过js给$scope创建的属性)

        下面再来看看ng-controller中通过ng-repeat创建的属性作用域

        第一个属性作用域,在里面有父作用域中的appName和names,而且又多了个a的属性,注意names集合中对象的值里多了个我在js里没有定义的$$hashKey,这个东西应该就是model values。


        第二个属性作用域也就大同小异了,可以看到唯一的区别就是$$hashKey的值


         既然子作用域可以用父作用域的值,那我就不免想到用子作用域更改值,会产生什么影响,以下是改变后浏览器的变化

         因为我的input标签与appName实现了双向数据绑定,可以看到我更改appName后,分割线上的{{appName}}无改变,而ng-controller($scope)中的{{appName}}改变了。


        来看看这个时候ng-app($root)的作用域,很明显appName没有改变,那么ng-controller($scope)里的appName为什么变了呢?

        带着疑问,我又看了ng-controller($scope)的作用域,没错,里面的appName改变了,再做了相关的查阅后,总结出一个原因:ng-controller生成的作用域创建了新的appName变量,而不是去修改$root中设定的appName的值,而如果想要修改,可以利用<input ng-model="$parent.appName">明确的引用父作用域来实现。

       
        以上是这篇笔记中的所有尝试。

TIP

        anguler js中官方定义的属性前都有个$符号,所以呢,我们创建自己的变量时就最好不要加$了,这样也方便查看,然后Firefox有个查看angular js作用域的工具,叫做Angscope,很有用,我就拿它来验证自己对作用域的猜想。

       sublime的一个快捷键,alt+shift+数字,可以实现分屏,蛮实用的。
0 0