Angularjs (一)

 

1、Angular是一款优秀的前端js框架,用它可以轻松构建SPA(Single Page Application,单页面应用程序) ,它的特征是:具有mvc的架构模式,便于模块化开发,自动化双向数据绑定和特有的指令系统。它最大限度的解放了Dom操作,让js代码更专注于业务逻辑的实现,通过简单的指令,结合页面结构和逻辑数据,通过自定义指令,实现组件化编程,代码结构更合理,维护成本更低。

2、Angular的应用完全没有自己写dom操作的地方。通过一些ng指令来完成事件绑定以及赋值,当我们写网页或者其他Angular应用时应注意的就是程序逻辑的地方,而不用去关注dom操作,减少了大量的代码量。这更符合面向对象编程,让框架去处理dom而我们只去处理逻辑。

3、如何使用Angular
在HTML代码中引入Angular.js包
在HTML代码中将刚刚定义的模块通过ng-app="yourModuleName"指令的方式作用到一个特定的元素上
在JS代码中通过angular.module('yourModuleName', []) 注册一个模块
根据当前页面的情况(业务块)划分控制器
在HTML代码中将刚刚定义的控制器通过ng-controller="ControllerName"作用到特定的元素上
建模(根据界面原型抽象一个数据模型)得到一个视图模型(ViewModel)
在JS代码中通过$scope暴露需要提供到页面的数据成员
在HTML代码中将刚刚暴露出来的数据通过类似ng-model/{{}}/ng-click之类的指令绑定到特定的元素上
在JS中完成业务逻辑

4、ng中是怎么样处理指令的
当浏览器渲染一个页面时,本质上是读html标识,然后建立dom节点,当dom树创建完毕之后广播一个事件给我们.
当你在页面中使用script标签加载ng应用程序代码时,ng监听上面的dom完成事件,查找带有ng-app属性的元素.
当找到这样的元素之后,ng开始处理dom以这个元素的起点,所以假如ng-app被添加到html元素上,则ng就会从html元素开始处理dom.
从这个起点开始,ng开始递归查找所有子元素里面,符合应用程序里定义好的指令规则.

5、angular程序的控制器必须在ng-app的范围之内,否则失效。 
ng-model是用于表单的模型,用于代替表单的值,用作和程序之间交流的模型,可以进行双向的数据绑定 。

 {{}}表达式只能够单向的绑定数据。实现从逻辑层到视图层的单向绑定,呈现数据。

6、service 
在angular中,service都是单例的,几乎每一个学习的教程中都会提到这一点,
并加以强调。单例的意思是说,在整个的应用中,每一个service对象只会被实
例化一次,其他地方对这个对象的操作,会影响到全局。

7、service 、provider、factory  

 

首先,有个东西需要说一下。以往在Js中,我们写了大量的代码来存取变量值,在angular中我们找到了一个比较好的

 

方法。然后,刚开始写angular的时候,我们容易把数据放的乱七八糟,有时候各种$scope, 各种域, 各种controller

 

的问题,这样其实就失去了angular的优势,angular的设计中 controller层是很薄的,一些业务逻辑的处理和数据持

 

化的问题需要放到service中。出于内存的考虑,controller只有在需要的时候才会被初始化,不需要的的时候就会

 

被抛弃。所以说,当你刷新页面时,controller就会被清空。而service就可以用来保存应用数据,并且可以在不同的

 

域中被使用。

 

(1)用Factory就是创建一个对象,添加了一定的属性之后,把它返回回来。你把service传进controller之后,在

 

controller里这个对象里的属性就可以通过factory使用了。

 

app.controller('myFactoryctrl', function($scope, myfactory){
    $scope.artist = myFactory.getArtist();
});
app.factory('myfactory', fuction(){
    var _artist = '';
    var service = {};
    service.getArtist = fuction(){
        return _artist;
    }
    return service;
});

 

(2) service 是用‘new’ 关键字实例化的。因此,你应该给‘this’添加属性,然后 service返回‘this’,把service传进cont

roller之后,在controller里的‘this’ 上的属性就可以通过service来使用了。

app.controller('myServicectrl',function($scope, myService){
    $scope.artist =myService.getArtist();
});
app.service('myService', function(){
    var _artist = 'Nelly';
    this.getArtist = function(){
        return _artist;
    }
});

 

(3)provider 是唯一一种可以传进config()函数的service。当你想要在service对象启用之前,先进行模块范围的配

置,那就应该使用provider.

app.controller('myProviderCtrl', function($scope, myProvider){
    $scope.artist = myProvider.getArtist();
    $scope.data.thingFromConfig = myProvider.thingOnConfig;
});
app.provider('myProvider', function(){
    this._artist = '';
    this.thingFromConfig = '' ;
    this,$get = function(){
        var that = this;
        return {
        getArtist:function(){
            return that._artist;
        }
        thingOnConfig: that.thingFromConfig
    }
    }
});

app.config(function(myProviderProvider){
    myProviderProvider.thingFromConfig = 'this was set in config()';
});

 

最后,强调一点,当我们需要在不同的域中共享数据的时候,我们最好用 service来实现. 

8、关于directive里的link和controller区别?

(1)、执行顺序:先controller后link
(2)、何时使用controller:一般场景下都不想要使用controller,只需要把逻辑写在link中就可以了;用controller的场景就是该指令(假设为a)会被其他指令(假设为b)require的时候,这样就会在b指令的link函数中传入这个controller(如果require多个的话,传入的是一个数组,数组中存放的是每一个require的指令对应的controller),目的很显然是为了指令间进行交流的。

9、关于非directive的scope能否用link?
在指令中才存在调用link的时候,也就是说link是该指令在compile之后和scope进行绑定的时候调用的。
那只有在指令定义的那个地方用到link了,其他地方也可以用,例如做弹出框的时候就需要,拿到模板tpl,然后调用var linkFn = $compile(angular.element(tpl));此时返回的就是一个link的函数,然后linkFn(scope),这里的scope是你需要指定的scope,可以是新创建的,也可以是已经存在的。

 

10、为什么编译的过程要分成compile和link?

 

简单的说就是为了解决性能问题,特别是那种model变化会影响dom结构变化的,而变化的结构还会有新的scope绑定及事件绑定,比如ng-repeat

compilelink的形式

compile

  • function compile(element, attrs, transclude) { ... }
  • 在compile阶段要执行的函数,返回的function就是link时要执行的function
  • 常用参数为elementattrs,分别是dom元素和元素上的属性们,其它的以后细说
  • 较少使用,因为大部分directive是处理dom元素的行为绑定,而不是改变它们

link

  • function link(scope, element, attrs, controller) { ... }
  • 在link阶段要执行的函数,这个属性只有当compile属性没有设置时才生效
  • 常用参数为scopeelementattrs,分别是当前元素所在的scope,dom元素和元素上的属性们,其它的以后细说
  • directive基本上都会有此函数,可以注册事件,并与scope相绑

compilelink的使用时机

compile

  • 想在dom渲染前对它进行变形,并且不需要scope参数
  • 想在所有相同directive里共享某些方法,这时应该定义在compile里,性能会比较好
  • 返回值就是link的function,这时就是共同使用的时候

link

  • 对特定的元素注册事件
  • 需要用到scope参数来实现dom元素的一些行为

 

11、作用域和控制器 

控制器是通过增强作用域来提供业务逻辑的代码。这是我们在作用域这个角度为它下的一个定义。注册的控制器在

ng-controller指令连接到AngularJS模板时被实例化的。每个控制器都会有一个自己的单独的子作用域,至于在自定

义指令中的$scope,是与控制器作用域同级的,和控制器作用域并没有任何的隶属关系。

 

12、作用域和模板 

模板是用来为Angular提供视图的。在模板中定义AngularJS指令时,可以使用作用域属性和函数。在模板的表达式中

也可以引用作用域中的属性。

 

13、作用域生命周期 

创建->监视器注册->模型变化->变化观察->作用域销毁

创建阶段发生在作用域初始化时。启动应用时将创建一个根作用域,当遇到ng-controller或者ng-repeat指令时,控制

器或者指令链接到模板时,将会创建子作用域。在创建阶段,将会创建一个digest循环,用于与浏览器时间循环交

互。该digest循环负责使用模型的变化更新DOM元素,并执行所有已经注册的监视器函数。如果需要手动的执行dig

est循环,可以通过执行$digest()方法实现. 例如,下面的代码将执行所有的异步改动,然后执行作用域中的监视函

数。

 

 

$scope.$digest()

 

我们可以用$watch()方法在作用域上注册自己的监视函数。该方法接受两个参数,一个是作用域属性的名字,一个

是回调函数。

$scope.$watch('name', function(newValue, oldValue) {

});

3.作用域层次问题 

这里有一个来自《Angular Js开发秘籍》的Demo,简单明了。

scopeDemo.js

angular.module('myApp',[])
.controller('LevelA', function($scope){
    $scope.title = "LevelA";
    $scope.valueA = 1;
    $scope.inc = function(){
        $scope.valueA++;
    };
})
.controller('LevelB', function($scope){
    $scope.title = "LevelB";
    $scope.valueB = 1;
    $scope.inc = function(){
        $scope.valueB++;
    };
})
.controller('LevelC', function($scope){
    $scope.title = "LevelC";
    $scope.valueC = 1;
    $scope.inc = function(){
        $scope.valueC++;
    };
});


HTML:

 

<!doctype html>
<html ng-app="myApp">
<head>
  <title>AngularJS Scope</title>
</head>
<body>
  <div ng-controller="LevelA">
    <h3>{{h3}}</h3>
    ValueA = {{valueA}}<input type="button" ng-click="inc()" value="+" />
    <div ng-controller="LevelB"><hr>
      <h3>{{title}}</h3>
      ValueA = {{valueA}}<br>
      ValueB = {{valueB}}<br>
      <input type="button" ng-click="inc()" value="+" />
      <div ng-controller="LevelC"><hr>
        <h3>{{title}}</h3>
        ValueA = {{valueA}}<br>
        ValueB = {{valueB}}<br>
        ValueC = {{valueC}}
        <input type="button" ng-click="inc()" value="+" />
      </div>
    </div>
  </div>
  <script src="js/angular.min.js"></script>
  <script src="scopeDemo.js"></script>
</body>
</html>

 

 

14、在debugger中查看scope:

(1). 在浏览器中,对着感兴趣的元素点击右键,选择“查看元素”。我们可以看到浏览器debugger高亮了我们选中的元素。

(2). debugger允许我们在console中通过$0变量去访问当前选择的元素。

(3). 想查看关联的scope,我们可以在console中输入:angular.element($0).scope()

 

15、$on、$emit和$broadcast的使用

  • $emit只能向parent controller传递event与data
  • $broadcast只能向child controller传递event与data
  • $on用于接收event与data

在一个controller里面通过事件触发一个方法,在方法里面通过$broadcast或$emit来定义一个变量,在父,子controller里面通过$on来获取。

 

 

parent用$broadcast赋的值,只能子级得到值;$emit赋的值,只能父级得到;而平级的什么都不能得到。

例子:

 

<!DOCTYPE HTML>
<html lang="zh-cn" ng-app = "myApp">
<head>
  <meta charset="UTF-8">
  <title>scope-event-propagation</title>
  <style type="text/css">
    .ng-cloak {
      display: none;
    }
    .ng-scope {
      border: 1px dashed red;
    }
  </style>
</head>
<body class="ng-cloak">
  <div ng-controller="MyController">
    root scope count:{{count}}
    <ul>
      <li ng-repeat="i in [1]" ng-controller="MyController">
        <button ng-click="$emit('MyEvent')">$emit("MyEvent")</button>
        <button ng-click="$broadcast('MyEvent')">$broadcast("MyEvent")</button>
        <br/>
        middle scope count:{{count}} //平级
        <ul>
          <li ng-repeat="item in [1,2]" ng-controller="MyController">
            Leaf scope count:{{count}}
          </li>
        </ul>
      </li>
    </ul>
  </div>
</body>
<script src = "js/angular.min.js"></script>
<script src="demo.js">
</script>
</html>

 

demo.js

angular.module('myApp', [])
.controller("MyController", function ($scope) {
	$scope.count = 0;
	$scope.$on("MyEvent", function() {
		$scope.count++;
	});
})

 

 

16、我们通过使用angular.element(aDomElement).scope()查看任意DOM元素的scope。

 

17、模块定义

 

angular.module("app", []);
      angular.module("app").controller("testCtrl", ["$scope", function ($scope) {
          $scope.currentMenu = "menu1";
          $scope.selectMenu = function (menu) {
              $scope.currentMenu = menu;
          }
      }]);

 

  • 我给ng-app指定了一个名称叫”app“,同时js代码使用angular.module("app", []);定义了一个名称为”app“的module,同时用这个app module 的controller方法定义了一个testCtrl;定义module函数是angular对象上的静态方法,第一个参数传名称,第二个参数是一个数组,这个数组表示这个module所引用的其他module,在这个例子中我们没有使用任何其他的module,所以传入一个空的数组,如果第二个参数不传,表示获取名称为”app“的module

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值