js实例教程-AngularJS的作用域与事件详解

发布时间:2018-11-27 发布网站:脚本宝典
脚本宝典收集整理的这篇文章主要介绍了js实例教程-AngularJS的作用域与事件详解脚本宝典觉得挺不错的,现在分享给大家,也给大家做个参考。
小宝典致力于为广大程序猿(媛)提供高品质的代码服务,请大家多多光顾小站,小宝典在此谢过。

一、AngularJS作用域详解

1.$rootScoPE

AngularJS作用域本质上就是一个普通的JavaScript对象,与普通的JavaScript一样,不同的是不需要手动去构造作用域对象,当HTML页面出现ng-app和ng-controller指令时,AngularJS框架会自动创建作用域对象,只需要注入即可

每个AngularJS应用至少有一个$rootScope,它是AngularJS应用的根作用域,事实上$rootScope是所有作用域的父作用域(孤立作用域除外)

当AngularJS启动时会自动创建一个$rootScope,接着当使用ng-controller指令实例化控制器对象时,AngularJS框架会为我们创建一个子作用域$scope,默认情况下,该$scope会继承$rootScope的所有属性

-------------------------------------------------controller.js----------------------------------------------------

VAR app=angular.module("app",[]);

app.controller('FirstController',function($scope,$LOG){

$log.info("FirstController->"+$scope.name);

$log.info("FirstController->"+$scope.age);

});

------------------------------------------------------app.htML---------------------------------------------------

<!DOCTYPE html>

<html ng-app="app">

<head>

<;meta charset="utf-8">

<tITle>angularjs</title>

<script type="text/javascript" src="angular.min.js"></script>

<script type="text/javascript" src="controller.js"></script>

</head>

<body ng-init="name='jane';age='23'">

<p ng-controller="FirstController"></p>

</body>

</html>

--------------------------------------------------------------------------------------------------------------------

2.可以在ng-controller指令所在范围内使用另一个ng-controller指令实现作用域嵌套,后者会继承前者的作用域

二、AngularJS的作用域继承

1.JavaScript对象继承机制

严格来讲,JavaScript并不是一门面向对象语言,而是一门基于对象的语言

1.1.JavaScript构造对象

(1).通过字面量创建

var obj= {name:'Schuyler',age:'33'};

(2).通过构造方法

function Person(name,age){

this.name=name;

this.age=age;

this.eat=function(){

console.log("eat...");

}

}

----------------

var person=new Person("Schuyler",33);

1.2.构造方法原型链继承

每个JavaScript构造器方法都有一个PRototype属性,可以指向另一个对象,当@H_512_88@

我们访问对象属性时,JavaScript引擎会从对象的所有属性中查找该属性,如果没有

找到就继续从prototype属性指向的对象中查找,如果仍没有找到,则会沿着

prototype链一直查找下去,直到prototype链结束或找到对象为止

--------------------------------------------------------------------------------------------------------------------

<!DOCTYPE html>

<html>

<head>

<meta charset="utf-8">

<title>angularjs</title>

</head>

<body>

<script type="text/javascript">

function Animal(){

this.eat=function(){

console.log('eat..');

}

}

function Cat(age){

this.age=age;

}

Cat.prototype= new Animal();

var cat=new Cat(10);

console.log("cat.age="+cat.age);

cat.eat();

</script>

</body>

</html>

--------------------------------------------------------------------------------------------------------------------

1.3.使用apply、call方法实现继承

JavaScript构造方法的apply()、call()方法可以改变对象构造中的"this"的上下

文环境,使特定对象的实例具有对象构造中所定义的属性、方法,因此我们可以使用

apply()、call()方法实现JavaScript对象的继承

--------------------------------------------------------------------------------------------------------------------

<!DOCTYPE html>

<html>

<head>

<meta charset="utf-8">

<title>angularjs</title>

</head>

<body>

<script type="text/javascript">

function Person(name,age){

this.name=name;

this.age=age;

}

function Student(name,age,love){

//Person.apply(this,[name,age]);

Person.call(this,name,age);

this.love=love;

}

var student=new Student("Schuyler",23,"code");

console.log("student.name="+student.name);

console.log("student.age="+student.age);

console.log("student.lpve="+student.love);

</script>

</body>

</html>

--------------------------------------------------------------------------------------------------------------------

1.4.对象实例间继承

Object.create()方法是以一个对象为原型创建另一个对象,创建的对象和原型具

有相同的属性,我们可以通过Object.getPrototypeOf()方法获取新对象的原型

--------------------------------------------------------------------------------------------------------------------

<!DOCTYPE html>

<head>

<meta charset="utf-8">

<title>angularjs</title>

</head>

<body>

<script type="text/javascript">

function Person(name,age){

this.name=name;

this.age=age;

}

var person = new Person('jane',28);

var student = Object.create(person);

student.love="pingpong";

console.log(Object.getPrototypeOf(student));

console.log("student.name->:"+student.name);

console.log("student.age->:"+student.age);

console.log("student.love->:"+student.love);

</script>

</body>

</html>

--------------------------------------------------------------------------------------------------------------------

2.AngularJS作用域对象原型继承

AngularJS作用域对象继承采用第一种方式,即构造器方法原型链继承。AngularJS作用域构造方法中提供了一个$new()成员方法,用于创建子作用域。过程大致如下:

var parent=$rootScope;

var child=parent.$new();

三、作用域高级特性

1.$watch()方法监视作用域

在使用AngularJS编写应用时,我们经常需要对作用域中的属性进行监视,并对其发生的变化做出相应的处理,AngularJS提供了帮助我们监视作用域属性变化的方法:$watch()

原理:在AngularJS内部,每当我们对ng-model绑定的属性进行一次修改时,AngularJS内部的$digest循环就会运行一次,并在运行结束之后检查我们使用$watch()方法来监视的内容,如果和上一次进行$digest之前相比有了变化,就执行我们使用$watch()方法绑定的处理函数

$watch()方法可以接受三个参数,第一个参数是需要监视的属性名称;第二个参数是监视属性发生变化时需要回调的方法,该方法可以传入两个参数,即变化的新值和旧值(可以不传);第三个参数可以不传,默认为false,称为"引用监视","引用监视"下只要监视的对象引用没有发生变化就不算发生变化,当设置为true时,称为"全等监视",此时只要监视的属性发生变化,$watch()就会执行相应的回调方法

"全等监视"在运行时需要先遍历整个监视对象,然后在每次$digest之前使用angular.copy()将整个对象深复制一遍,然后再运行之后用angular.equal()将前后的对象进行对比,因此在大量数据的复杂环境下可能会消耗大量的资

另外有$watchCollection()方法来针对数组进行监视,它不会对数组中的每一项属性进行监视,但是可以对数组元素的增减做出反应

------------------------------------------------监视基本类型属性--------------------------------------------

<!DOCTYPE html>

<html ng-app="app">

<head>

<meta charset="utf-8">

<title>angularjs</title>

<script type="text/javascript" src="angular.min.js"></script>

</head>

<body>

<input type="text" ng-model='name'/>

<p>change count:{{count}}</p>

<script type="text/javascript">

angular.module('app',[])

.run(['$rootScope',function($rootScope){

&nbsp; $rootScope.count=0;

  $rootScope.name="江荣波";

  $rootScope.$watch('name',function(){

  $rootScope.count++;

  })

}]);

</script>

</body>

</html>

-------------------------------------------------监视引用类型属性-------------------------------------------

<!DOCTYPE html>

<html ng-app="app">

<head>

<meta charset="utf-8">

<title>angularjs</title>

<script type="text/javascript" src="angular.min.js"></script>

</head>

<body>

<p ng-repeat='iteam in items'>

<input ng-model='item.value'/>

<span>{{item.value}}</span>

<br/><br/>

</p>

<p>change count:{{count}}</p>

<script type="text/javascript">

angular.module('app',[])

.run(['$rootScope',function($rootScope){

  $rootScope.count=0;

  $rootScope.items=[{"value":1},{"value":2},{"value":3},{"value":4}];

  $rootScope.$watch('name',function(){

  $rootScope.count++;

  });

}]);

</script>

</body>

</html>

--------------------------------------------------------------------------------------------------------------------

2.作用域监视解除

$watch()方法的返回值,该方法调用完毕后会返回一个方法,调用该方法即可解除作用域监视

--------------------------------------------------------------------------------------------------------------------

<!DOCTYPE html>

<html ng-app="app">

<head>

<meta charset="utf-8">

<title>angularjs</title>

<script type="text/javascript" src="angular.min.js"></script>

</head>

<body>

<input ng-model='num' type='number'/>

<p>change count:{{count}}</p>

<script type="text/javascript">

angular.module('app',[])

.run(['$rootScope',function($rootScope){

  $rootScope.count=0;

  $rootScope.num=100;

 var unbindWatch=

$rootScope.$watch('num',function(newValue,oldValue){

  if(newValue==2){

unbindWatch();

  }

  $rootScope.count++;

  });

}]);

</script>

</body>

</html>

--------------------------------------------------------------------------------------------------------------------

3.$apply方法与$digest循环

AngularJS周期性地运行一个函数来检查scope模型中的数据是否发生了变化,这就是所谓的$digest循环

当写下AngularJS的表达式({{name}})时,AngularJS框架会在幕后为我们在$scope中设置一个watcher(与手动$watch()方法添加的watcher一样),用来在数据发生变化的时候更新View

假设在ng-click指令对应的事件处方法中更改了scope中的一条数据,此时AngularJS会自动的通过调用$digest()来触发一轮$digest循环,通常,AngularJS并不直接调用$digest()方法,而是调用$scope.$apply(),后者会调用$rootScope.$digest(),因此一轮$digest循环在$rootScope开始,随后会访问所有子作用域中的watcher

在$digest循环中会触发每一个watcher,检测scope模型是否发生了变化,如果发生了变化,那么关联到该watcher的回调方法就会被调用

除了ng-click指令,还有一些其他的AngularJS内置指令和服务,比如ng-model、$timeout服务等,让我们能够更改模型数据和自动触发一次$digest循环

4.$apply与$digest应用实战

当作用域中的模型数据发生变化时,AngularJS会自动触发$digest循环,从而达到自动更新视图的目的。但有些情况下时需要自己手动调用$apply()方法来触发$digest循环的,例如使用JavaScript的setTimeout()方法来更新一个模型数据,此时AngularJS无法知道我们修改了什么,也就无法触发$digest循环

--------------------------------------------------------------------------------------------------------------------

<!DOCTYPE html>

<html ng-app="app">

<head>

<meta charset="utf-8">

<title>angularjs</title>

<script type="text/javascript" src="angular.min.js"></script>

</head>

<body>

<p ng-controller="MsgController">

<p>

<button ng-click="scheduleTask()">3秒回显信息

</button>

</p>

<p>{{message}}</p>

</p>

<script type="text/javascript">

angular.module("app",[])

.controller("MsgController",

function($scope){

$scope.scheduleTask=function(){

setTimeout(function(){

$scope.message='信息内容';

console.log('message='+$scope.message);

},3000)

}

});

</script>

</body>

</html>

--------------------------------------------------------------------------------------------------------------------

此时需要手动调用$apply()方法来触发$digest循环,$apply()方法接受一个方法作为参数

--------------------------------------------------------------------------------------------------------------------

<script type="text/javascript">

angular.module("app",[])

.controller("MsgController",

function($scope){

$scope.scheduleTask=function(){

setTimeout(function(){

      $scope.$apply(function(){

$scope.message='信息内容';

console.log('message='+$scope.message);

});

  },3000)

}

});

</script>

--------------------------------------------------------------------------------------------------------------------

5.$timeout与$interval服务介绍

$timeout和$interval是AngularJS提供的功能和JavaScript的setTimeout()、setInterval()相同的两个服务,使用这两个服务修改作用域属性时会自动触发$digest循环

--------------------------------------------------------------------------------------------------------------------

<!DOCTYPE html>

<html ng-app="app">

<head>

<meta charset="utf-8">

<title>angularjs</title>

<script type="text/javascript" src="angular.min.js"></script>

</head>

<body>

<p ng-controller="MsgController">

<p>

<button ng-click="scheduleTask()">3秒回显信息

</button>

</p>

<p>{{message}}</p>

</p>

<script type="text/javascript">

angular.module("app",[])

.controller("MsgController",

function($scope,$timeout){

$scope.scheduleTask=function(){

$timeout(function(){

$scope.message='信息内容';

console.log('message='+$scope.message);

},3000)

}

});

</script>

</body>

</html>

--------------------------------------------------------------------------------------------------------------------

四、作用域事件路由与广播

事件传播机制是AngularJS作用域的另外一个优秀特性,在一些情况下需要在控制器中对一些事件做出处理,例如Ajax请求完成事件,需要通知控制器处理服务端返回的数据,作用域事件传播机制可以帮我们完成这些操作;当我们需要在控制器直接传递数据时,也可以使用作用域事件机制来完成

AngularJS作用域支持两种事件传播方式:

(1).事件从子作用域路由到父作用域中

(2).事件从父作用域广播到所有子作用域中

与AngularJS作用域事件相关的方法有$on()、$emit()、$broadcast()

1.$emit()方法实现事件路由(第一种传播方式)

AngularJS作用域对象提供了$emit()方法,用于实现事件从子作用域路由到父作用域中,第一个参数为事件名称,后面可以传入一个或多个参数,这些参数能被传递到父作用域注册的事件监听器中

在父作用域中调用AngularJS作用域对象的$on()方法,注册一个事件监听器监听子作用域路由的事件,第一个参数为事件名称,第二个参数为事件监听器定义部分,它接收两个参数,第一个参数为事件对象,第二个参数为子作用域中传递的数据

--------------------------------------------------------------------------------------------------------------------

<!DOCTYPE html>

<html ng-app="app">

<head>

<meta charset="utf-8">

<title>angularjs</title>

<script type="text/javascript" src="angular.min.js"></script>

<style type="text/css">

#parent{

width:350px;

height:250px;

border:3px solid #ccc;

}

#child{

width:300px;

height:200px;

border:3px solid #ccc;

margin:10px auto;

}

</style>

</head>

<body>

<p id="parent" ng-controller="ParentController">

父作用域

<p id="child" ng-controller="ChildController">

子作用域<button ng-click="postEvent()">Emit</button>

</p>

</p>

<script type="text/javascript">

var app=angular.module("app",[]);

app.controller('ParentController',

function($scope){

$scope.$on("infoEvent",function(event,data){

console.log("接收到子作用域事件...");

console.log(data);

});

});

app.controller('ChildController',

function($scope){

$scope.postEvent=function(){

$scope.$emit("infoEvent",{name:"Schuyler",age:23});

}

});

</script>

</body>

</html>

--------------------------------------------------------------------------------------------------------------------

2.$broadcast()方法实现事件广播(第二种传播方式)

$broadcast()方法的使用与$emit()方法相同,不过是由父作用域来广播事件,子作用域只要通过$on()方法注册事件监听器即可

--------------------------------------------------------------------------------------------------------------------

<!DOCTYPE html>

<html ng-app="app">

<head>

<meta charset="utf-8">

<title>angularjs</title>

<script type="text/javascript" src="angular.min.js"></script>

<style type="text/css">

#parent{

width:450px;

height:250px;

border:3px solid #ccc;

}

.child{

width:150px;

height:200px;

border:3px solid #ccc;

float:left;

margin-left:20px;

}

</style>

</head>

<body>

<p id="parent" ng-controller="ParentController">

<p>父作用域

      <button ng-click="postEvent()">Broadcast</button>

   </p>

<p class="child" ng-controller="Child1Controller">

子作用域1

</p>

<p class="child" ng-controller="Child2Controller">

子作用域2

</p>

</p>

<script type="text/javascript">

   var app=angular.module("app",[]);

   app.controller('ParentController',

function($scope){

$scope.postEvent=function(){

$scope.$broadcast("infoEvent",{name:"Schuyler",age:23});

}

});

    app.controller('Child1Controller',

function($scope){

$scope.$on("infoEvent",function(event,data){

console.log("子作用域1接收到父作用域事件...");

console.log(data);

});

});

   app.controller('Child2Controller',

function($scope){

$scope.$on("infoEvent",function(event,data){

console.log("子作用域2接收到父作用域事件...");

console.log(data);

});

});

</script>

</body>

</html>

--------------------------------------------------------------------------------------------------------------------

3.作用域对象$on方法详解

$on()方法用于注册一个事件监听器,该方法接收两个参数,第一个参数是要监听的事件的名称,第二个参数是事件处理方法

$scope.$on("infoEvent",function(event,data){……});

事件处理方法接收两个参数,第一个参数event为事件对象,第二个参数data为调用$emit()或$broadcast()方法传递的数据

event事件对象具有一些实用的属性和方法:

event.name:事件名称

event.targetScope:事件源作用域对象

event.currentScope:当前作用域对象

event.stopPropagation():停止事件的进一步传播,只对向父作用域路由事件

起作用,当在某个事件监听处理方法中调用事件对象的stopPropagation()方法

后,事件将不会再向上级父作用域路由。对$broadcast()无效

event.preventDefault():将defaultPrevented属性设置为true

一、AngularJS作用域详解

1.$rootScope

AngularJS作用域本质上就是一个普通的JavaScript对象,与普通的JavaScript一样,不同的是不需要手动去构造作用域对象,当HTML页面出现ng-app和ng-controller指令时,AngularJS框架会自动创建作用域对象,只需要注入即可

每个AngularJS应用至少有一个$rootScope,它是AngularJS应用的根作用域,事实上$rootScope是所有作用域的父作用域(孤立作用域除外)

当AngularJS启动时会自动创建一个$rootScope,接着当使用ng-controller指令实例化控制器对象时,AngularJS框架会为我们创建一个子作用域$scope,默认情况下,该$scope会继承$rootScope的所有属性

-------------------------------------------------controller.js----------------------------------------------------

var app=angular.module("app",[]);

app.controller('FirstController',function($scope,$log){

$log.info("FirstController->"+$scope.name);

$log.info("FirstController->"+$scope.age);

});

------------------------------------------------------app.html---------------------------------------------------

<!DOCTYPE html>

<html ng-app="app">

<head>

<meta charset="utf-8">

<title>angularjs</title>

<script type="text/javascript" src="angular.min.js"></script>

<script type="text/javascript" src="controller.js"></script>

</head>

<body ng-init="name='jane';age='23'">

<p ng-controller="FirstController"></p>

</body>

</html>

--------------------------------------------------------------------------------------------------------------------

2.可以在ng-controller指令所在范围内使用另一个ng-controller指令实现作用域嵌套,后者会继承前者的作用域

二、AngularJS的作用域继承

1.JavaScript对象继承机制

严格来讲,JavaScript并不是一门面向对象语言,而是一门基于对象的语言

1.1.JavaScript构造对象

(1).通过字面量创建

var obj= {name:'Schuyler',age:'33'};

(2).通过构造方法

function Person(name,age){

this.name=name;

this.age=age;

this.eat=function(){

console.log("eat...");

}

}

----------------

var person=new Person("Schuyler",33);

1.2.构造方法原型链继承

每个JavaScript构造器方法都有一个prototype属性,可以指向另一个对象,当

我们访问对象属性时,JavaScript引擎会从对象的所有属性中查找该属性,如果没有

找到就继续从prototype属性指向的对象中查找,如果仍没有找到,则会沿着

prototype链一直查找下去,直到prototype链结束或找到对象为止

--------------------------------------------------------------------------------------------------------------------

<!DOCTYPE html>

<html>

<head>

<meta charset="utf-8">

<title>angularjs</title>

</head>

<body>

<script type="text/javascript">

function Animal(){

this.eat=function(){

console.log('eat..');

}

}

function Cat(age){

this.age=age;

}

Cat.prototype= new Animal();

var cat=new Cat(10);

console.log("cat.age="+cat.age);

cat.eat();

</script>

</body>

</html>

--------------------------------------------------------------------------------------------------------------------

1.3.使用apply、call方法实现继承

JavaScript构造方法的apply()、call()方法可以改变对象构造中的"this"的上下

文环境,使特定对象的实例具有对象构造中所定义的属性、方法,因此我们可以使用

apply()、call()方法实现JavaScript对象的继承

--------------------------------------------------------------------------------------------------------------------

<!DOCTYPE html>

<html>

<head>

<meta charset="utf-8">

<title>angularjs</title>

</head>

<body>

<script type="text/javascript">

function Person(name,age){

this.name=name;

this.age=age;

}

function Student(name,age,love){

//Person.apply(this,[name,age]);

Person.call(this,name,age);

this.love=love;

}

var student=new Student("Schuyler",23,"code");

console.log("student.name="+student.name);

console.log("student.age="+student.age);

console.log("student.lpve="+student.love);

</script>

</body>

</html>

--------------------------------------------------------------------------------------------------------------------

1.4.对象实例间继承

Object.create()方法是以一个对象为原型创建另一个对象,创建的对象和原型具

有相同的属性,我们可以通过Object.getPrototypeOf()方法获取新对象的原型

--------------------------------------------------------------------------------------------------------------------

<!DOCTYPE html>

<head>

<meta charset="utf-8">

<title>angularjs</title>

</head>

<body>

<script type="text/javascript">

function Person(name,age){

this.name=name;

this.age=age;

}

var person = new Person('jane',28);

var student = Object.create(person);

student.love="pingpong";

console.log(Object.getPrototypeOf(student));

console.log("student.name->:"+student.name);

console.log("student.age->:"+student.age);

console.log("student.love->:"+student.love);

</script>

</body>

</html>

--------------------------------------------------------------------------------------------------------------------

2.AngularJS作用域对象原型继承

AngularJS作用域对象继承采用第一种方式,即构造器方法原型链继承。AngularJS作用域构造方法中提供了一个$new()成员方法,用于创建子作用域。过程大致如下:

var parent=$rootScope;

var child=parent.$new();

三、作用域高级特性

1.$watch()方法监视作用域

在使用AngularJS编写应用时,我们经常需要对作用域中的属性进行监视,并对其发生的变化做出相应的处理,AngularJS提供了帮助我们监视作用域属性变化的方法:$watch()

原理:在AngularJS内部,每当我们对ng-model绑定的属性进行一次修改时,AngularJS内部的$digest循环就会运行一次,并在运行结束之后检查我们使用$watch()方法来监视的内容,如果和上一次进行$digest之前相比有了变化,就执行我们使用$watch()方法绑定的处理函数

$watch()方法可以接受三个参数,第一个参数是需要监视的属性名称;第二个参数是监视属性发生变化时需要回调的方法,该方法可以传入两个参数,即变化的新值和旧值(可以不传);第三个参数可以不传,默认为false,称为"引用监视","引用监视"下只要监视的对象引用没有发生变化就不算发生变化,当设置为true时,称为"全等监视",此时只要监视的属性发生变化,$watch()就会执行相应的回调方法

"全等监视"在运行时需要先遍历整个监视对象,然后在每次$digest之前使用angular.copy()将整个对象深复制一遍,然后再运行之后用angular.equal()将前后的对象进行对比,因此在大量数据的复杂环境下可能会消耗大量的资源

另外有$watchCollection()方法来针对数组进行监视,它不会对数组中的每一项属性进行监视,但是可以对数组元素的增减做出反应

------------------------------------------------监视基本类型属性--------------------------------------------

<!DOCTYPE html>

<html ng-app="app">

<head>

<meta charset="utf-8">

<title>angularjs</title>

<script type="text/javascript" src="angular.min.js"></script>

</head>

<body>

<input type="text" ng-model='name'/>

<p>change count:{{count}}</p>

<script type="text/javascript">

angular.module('app',[])

.run(['$rootScope',function($rootScope){

  $rootScope.count=0;

  $rootScope.name="江荣波";

  $rootScope.$watch('name',function(){

  $rootScope.count++;

  })

}]);

</script>

</body>

</html>

-------------------------------------------------监视引用类型属性-------------------------------------------

<!DOCTYPE html>

<html ng-app="app">

<head>

<meta charset="utf-8">

<title>angularjs</title>

<script type="text/javascript" src="angular.min.js"></script>

</head>

<body>

<p ng-repeat='iteam in items'>

<input ng-model='item.value'/>

<span>{{item.value}}</span>

<br/><br/>

</p>

<p>change count:{{count}}</p>

<script type="text/javascript">

angular.module('app',[])

.run(['$rootScope',function($rootScope){

  $rootScope.count=0;

  $rootScope.items=[{"value":1},{"value":2},{"value":3},{"value":4}];

  $rootScope.$watch('name',function(){

  $rootScope.count++;

  });

}]);

</script>

</body>

</html>

--------------------------------------------------------------------------------------------------------------------

2.作用域监视解除

$watch()方法的返回值,该方法调用完毕后会返回一个方法,调用该方法即可解除作用域监视

--------------------------------------------------------------------------------------------------------------------

<!DOCTYPE html>

<html ng-app="app">

<head>

<meta charset="utf-8">

<title>angularjs</title>

<script type="text/javascript" src="angular.min.js"></script>

</head>

<body>

<input ng-model='num' type='number'/>

<p>change count:{{count}}</p>

<script type="text/javascript">

angular.module('app',[])

.run(['$rootScope',function($rootScope){

  $rootScope.count=0;

  $rootScope.num=100;

 var unbindWatch=

$rootScope.$watch('num',function(newValue,oldValue){

  if(newValue==2){

unbindWatch();

  }

  $rootScope.count++;

  });

}]);

</script>

</body>

</html>

--------------------------------------------------------------------------------------------------------------------

3.$apply方法与$digest循环

AngularJS周期性地运行一个函数来检查scope模型中的数据是否发生了变化,这就是所谓的$digest循环

当写下AngularJS的表达式({{name}})时,AngularJS框架会在幕后为我们在$scope中设置一个watcher(与手动$watch()方法添加的watcher一样),用来在数据发生变化的时候更新View

假设在ng-click指令对应的事件处方法中更改了scope中的一条数据,此时AngularJS会自动的通过调用$digest()来触发一轮$digest循环,通常,AngularJS并不直接调用$digest()方法,而是调用$scope.$apply(),后者会调用$rootScope.$digest(),因此一轮$digest循环在$rootScope开始,随后会访问所有子作用域中的watcher

在$digest循环中会触发每一个watcher,检测scope模型是否发生了变化,如果发生了变化,那么关联到该watcher的回调方法就会被调用

除了ng-click指令,还有一些其他的AngularJS内置指令和服务,比如ng-model、$timeout服务等,让我们能够更改模型数据和自动触发一次$digest循环

4.$apply与$digest应用实战

当作用域中的模型数据发生变化时,AngularJS会自动触发$digest循环,从而达到自动更新视图的目的。但有些情况下时需要自己手动调用$apply()方法来触发$digest循环的,例如使用JavaScript的setTimeout()方法来更新一个模型数据,此时AngularJS无法知道我们修改了什么,也就无法触发$digest循环

--------------------------------------------------------------------------------------------------------------------

<!DOCTYPE html>

<html ng-app="app">

<head>

<meta charset="utf-8">

<title>angularjs</title>

<script type="text/javascript" src="angular.min.js"></script>

</head>

<body>

<p ng-controller="MsgController">

<p>

<button ng-click="scheduleTask()">3秒回显信息

</button>

</p>

<p>{{message}}</p>

</p>

<script type="text/javascript">

angular.module("app",[])

.controller("MsgController",

function($scope){

$scope.scheduleTask=function(){

setTimeout(function(){

$scope.message='信息内容';

console.log('message='+$scope.message);

},3000)

}

});

</script>

</body>

</html>

--------------------------------------------------------------------------------------------------------------------

此时需要手动调用$apply()方法来触发$digest循环,$apply()方法接受一个方法作为参数

--------------------------------------------------------------------------------------------------------------------

<script type="text/javascript">

angular.module("app",[])

.controller("MsgController",

function($scope){

$scope.scheduleTask=function(){

setTimeout(function(){

      $scope.$apply(function(){

$scope.message='信息内容';

console.log('message='+$scope.message);

});

  },3000)

}

});

</script>

--------------------------------------------------------------------------------------------------------------------

5.$timeout与$interval服务介绍

$timeout和$interval是AngularJS提供的功能和JavaScript的setTimeout()、setInterval()相同的两个服务,使用这两个服务修改作用域属性时会自动触发$digest循环

--------------------------------------------------------------------------------------------------------------------

<!DOCTYPE html>

<html ng-app="app">

<head>

<meta charset="utf-8">

<title>angularjs</title>

<script type="text/javascript" src="angular.min.js"></script>

</head>

<body>

<p ng-controller="MsgController">

<p>

<button ng-click="scheduleTask()">3秒回显信息

</button>

</p>

<p>{{message}}</p>

</p>

<script type="text/javascript">

angular.module("app",[])

.controller("MsgController",

function($scope,$timeout){

$scope.scheduleTask=function(){

$timeout(function(){

$scope.message='信息内容';

console.log('message='+$scope.message);

},3000)

}

});

</script>

</body>

</html>

--------------------------------------------------------------------------------------------------------------------

四、作用域事件路由与广播

事件传播机制是AngularJS作用域的另外一个优秀特性,在一些情况下需要在控制器中对一些事件做出处理,例如Ajax请求完成事件,需要通知控制器处理服务端返回的数据,作用域事件传播机制可以帮我们完成这些操作;当我们需要在控制器直接传递数据时,也可以使用作用域事件机制来完成

AngularJS作用域支持两种事件传播方式:

(1).事件从子作用域路由到父作用域中

(2).事件从父作用域广播到所有子作用域中

与AngularJS作用域事件相关的方法有$on()、$emit()、$broadcast()

1.$emit()方法实现事件路由(第一种传播方式)

AngularJS作用域对象提供了$emit()方法,用于实现事件从子作用域路由到父作用域中,第一个参数为事件名称,后面可以传入一个或多个参数,这些参数能被传递到父作用域注册的事件监听器中

在父作用域中调用AngularJS作用域对象的$on()方法,注册一个事件监听器监听子作用域路由的事件,第一个参数为事件名称,第二个参数为事件监听器定义部分,它接收两个参数,第一个参数为事件对象,第二个参数为子作用域中传递的数据

--------------------------------------------------------------------------------------------------------------------

<!DOCTYPE html>

<html ng-app="app">

<head>

<meta charset="utf-8">

<title>angularjs</title>

<script type="text/javascript" src="angular.min.js"></script>

<style type="text/css">

#parent{

width:350px;

height:250px;

border:3px solid #ccc;

}

#child{

width:300px;

height:200px;

border:3px solid #ccc;

margin:10px auto;

}

</style>

</head>

<body>

<p id="parent" ng-controller="ParentController">

父作用域

<p id="child" ng-controller="ChildController">

子作用域<button ng-click="postEvent()">Emit</button>

</p>

</p>

<script type="text/javascript">

var app=angular.module("app",[]);

app.controller('ParentController',

function($scope){

$scope.$on("infoEvent",function(event,data){

console.log("接收到子作用域事件...");

console.log(data);

});

});

app.controller('ChildController',

function($scope){

$scope.postEvent=function(){

$scope.$emit("infoEvent",{name:"Schuyler",age:23});

}

});

</script>

</body>

</html>

--------------------------------------------------------------------------------------------------------------------

2.$broadcast()方法实现事件广播(第二种传播方式)

$broadcast()方法的使用与$emit()方法相同,不过是由父作用域来广播事件,子作用域只要通过$on()方法注册事件监听器即可

--------------------------------------------------------------------------------------------------------------------

<!DOCTYPE html>

<html ng-app="app">

<head>

<meta charset="utf-8">

<title>angularjs</title>

<script type="text/javascript" src="angular.min.js"></script>

<style type="text/css">

#parent{

width:450px;

height:250px;

border:3px solid #ccc;

}

.child{

width:150px;

height:200px;

border:3px solid #ccc;

float:left;

margin-left:20px;

}

</style>

</head>

<body>

<p id="parent" ng-controller="ParentController">

<p>父作用域

      <button ng-click="postEvent()">Broadcast</button>

   </p>

<p class="child" ng-controller="Child1Controller">

子作用域1

</p>

<p class="child" ng-controller="Child2Controller">

子作用域2

</p>

</p>

<script type="text/javascript">

   var app=angular.module("app",[]);

   app.controller('ParentController',

function($scope){

$scope.postEvent=function(){

$scope.$broadcast("infoEvent",{name:"Schuyler",age:23});

}

});

    app.controller('Child1Controller',

function($scope){

$scope.$on("infoEvent",function(event,data){

console.log("子作用域1接收到父作用域事件...");

console.log(data);

});

});

   app.controller('Child2Controller',

function($scope){

$scope.$on("infoEvent",function(event,data){

console.log("子作用域2接收到父作用域事件...");

console.log(data);

});

});

</script>

</body>

</html>

--------------------------------------------------------------------------------------------------------------------

3.作用域对象$on方法详解

$on()方法用于注册一个事件监听器,该方法接收两个参数,第一个参数是要监听的事件的名称,第二个参数是事件处理方法

$scope.$on("infoEvent",function(event,data){……});

事件处理方法接收两个参数,第一个参数event为事件对象,第二个参数data为调用$emit()或$broadcast()方法传递的数据

event事件对象具有一些实用的属性和方法:

event.name:事件名称

event.targetScope:事件源作用域对象

event.currentScope:当前作用域对象

event.stopPropagation():停止事件的进一步传播,只对向父作用域路由事件

起作用,当在某个事件监听处理方法中调用事件对象的stopPropagation()方法

后,事件将不会再向上级父作用域路由。对$broadcast()无效

event.preventDefault():将defaultPrevented属性设置为true

觉得可用,就经常来吧!Javascript技巧 脚本宝典 欢迎评论哦! js技巧,巧夺天工,精雕玉琢。小宝典献丑了!

脚本宝典总结

以上是脚本宝典为你收集整理的js实例教程-AngularJS的作用域与事件详解全部内容,希望文章能够帮你解决js实例教程-AngularJS的作用域与事件详解所遇到的问题。

如果觉得脚本宝典网站内容还不错,欢迎将脚本宝典推荐好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。