Angularjs留存(一)

来源:互联网 发布:免越狱安装软件 编辑:程序博客网 时间:2024/06/05 15:14

PS:Angularjs留存系列主要是用来记录一些自己在学习其他文章时觉得有必要留存一下的fortune!

文章可能会很长(默认每篇17个小的知识点),但是我们可以使用Ctrl + F 来查找啦!


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;});
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11


(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;    }});
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

(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()';});
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21


最后,强调一点,当我们需要在不同的域中共享数据的时候,我们最好用 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()
  • 1

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

是回调函数。

$scope.$watch('name', function(newValue, oldValue){});
  • 1
  • 2
  • 3

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


1 0
原创粉丝点击