修真院Web工程师零基础全能课javascript
本节课内容html
AngularJs进阶-做用域和控制器java
主讲人介绍angularjs
沁修,葡萄藤技术总监数组
项目经验丰富,擅长H5移动项目开发。浏览器
专一技术选型、底层开发、最佳代码实践规范总结与推广。app
直播录屏版框架
传送门:https://v.qq.com/x/page/t0782...函数
文字解析版prototype
什么是scope做用域?
scope做用域是一个指向应用model的对象object,也是表达式的执行环境。
做用域有层次结构,有根做用域,有不少子做用域,根据位置不一样而不一样。
做用域还能监控表达式,传递事件。
好比在html当中,咱们都会定义一个ng-app指令,那么随之而来就是一个做用域产生了。
不过由ng-app生成的做用域比较特殊,它是一个根做用域$rootscope,也就是其余全部scope的顶层。
除此以外,还有不少指令都会产生一个做用域,好比ng-controller, ng-repeat等。这些做用域都拥有本身的继承上下文,而且根做用域都是rootscope。
在咱们生成一个做用域以后,$scope对象就表明了这个做用域的数据。
咱们能够在$scope内定义各类数据,以后能够直接在html中以双花括号的表达式的方式来让html获得这个变量。
scope的用法?
在正式开始接触scope以前咱们再来熟悉一下js的全局变量和局部变量:
var foo = "foo";
function bar() {
var foo = "bar";
console.log(foo);
}
bar();
console.log(foo);
这里说明,全局变量能够在方法内引入,而局部变量只能在定义的方法内使用,angular做用域跟变量性质类似。
angularjs中的全局做用域:
var myApp = angular.module('myApp', []);
/*
*/
myApp.run(function($rootScope){
$rootScope.version = 2.0;
});
全局做用域是全部controller的scope的桥梁。
rootscope定义的值,能够在各个controller中使用。
常常用于须要在多个页面场景中的数据就能够定义到全局做用域上。
angularjs中的局部做用域:
myApp.controller('homeCtrl', function($scope){
$scope.person = {
name: 'max'
}
})
myApp.controller('productCtrl',function($scope,$rootScope){
console.log($scope.person.name);//undefined
console.log($rootScope.version) //2.0
})
前面咱们已经说过,每个angular应用有且只有一个root scope,但能够拥有多个child scope。
由于一些directive会建立新的child scope,当新的scope被建立后,他们将做为一个child scope,加入到parent scope中。
这样,建立了一个与它们附属的DOM类似的树结构。
当angular在html中对{{person}}求值时,它首先查看与当前元素关联的scope的person属性。
若是没有找到对应的属性,它将会一直向上搜索parent scope,直到到达root scope。
在javascript中,这个行为被称为“原型继承”,child scope典型地继承自它们的parent。
$scope特色?
提供了$watch()方法,用于监听模型的变化
提供了$apply()方法,用于传播模型的变化
$watch()监听模型变化,当模型发生变化,它会给你提示。
表达式:
$watch(watchExpression, listener, objectEquality);
watchExpression:监听的对象,好比一个angular表达式如’scope.person’。
listener:当watchExpression变化时会被调用的函数或者表达式,它接收3个参数:
newValue(新值), oldValue(旧值), scope(做用域的引用)。
objectEquality:是否深度监听,若是设置为true,它告诉Angular检查所监控的对象中每个属性的变化.。
若是你但愿监控数组的个别元素或者对象的属性而不是一个普通的值, 那么你应该使用它。
$scope.name = 'hello';
$scope.$watch('name',function(newValue, oldValue, scope){
console.log(newValue);
console.log(oldValue);
});
$timeout(function(){
$scope.name = "world";
},1000);
$apply()用于传播模型的变化。
AngularJS 外部的控制器(DOM 事件、外部的回调函数如jQuery等)调用了AngularJS 函数以后,就须要调用$apply。
myApp.controller('homeCtrl', function($scope){
vm.name = 'hello';
setTimeout(function () {
vm.name = "world";
}, 2000);
})
预期的应该是先显示hello, 两秒后改成world。
但事实是咱们发现它不会自动变化,由于调研了外部的事件,因此须要用$apply方法就能够了:
myApp.controller('homeCtrl', function($scope){
vm.name = 'hello';
setTimeout(function () {
$scope.$apply(function () {
vm.name = "world";
});
}, 2000);
})
$scope的生命周期?
建立 creation
↓
注册监视器 watcher registration
↓
模型变化 model mutation
↓
变化检测 mutation observation
↓
做用域销毁 scope destruction
浏览器正常的事件流中,当浏览器接收到事件后,它会执行一个相应的javascript回调。
一旦回调函数执行完毕后,浏览器将会重绘DOM,并返回到继续等待事件的状态。
1.在应用启动的过程当中,会建立rootscope,然后在模板的连接过程当中,一些directive会建立新的child scope。
2.directive在scope中注册$watch,这些watch会用来向DOM传播model的值。
3.更新模型状态必须是在$apply方法中才能够被观察到,不过angular框架是封装了这个方法过程的。
咱们一般无需担忧,除非是以前提到过的,angular之外的一些方法事件在触发后,不能正常调用$apply才须要手动去添加这个方法。
4.$apply方法结束后,angular会在根做用域执行一个$digest周期而且扩散到全部子做用域。
scope检查全部$watch监听的表达式,将如今的值与旧的值做比较。
这个过程会检查模型状态是否改变以及更新。
5.销毁做用域,当不在须要子做用域的时候,就会被销毁掉。
总结$scope?
一、提供了观察者能够监听数据模型的变化
二、能够将数据模型的变化通知给整个 App
三、能够进行嵌套,隔离业务功能和数据
四、给表达式提供上下文执行环境
在scope以后咱们又来看看和它关系很是紧密的控制器controller。。。
什么是控制器?
从做用上来说,controller主要是对视图中的数据和事件函数进行挂载,同时处理一些业务的地方。
从功能上来说,在angularjs中,controller是一个js函数,用来扩展angular的子scope的实例。
所以它能够用来设置scope对象的初始状态,而且增长一些属性行为到scope中。
控制器使用?
在模板中声明控制器
<div ng-controller="myController">...</div>
控制器实际上就是一个js的构造函数:
//控制器类定义
var myControllerClass = function($scope){
//模型属性定义
$scope.text = "...";
//模型方法定义
$scope.do = function(){...};
};
//在模块中注册控制器
angular.module('someModule',[])
.controller("myController",myControllerClass);
控制器构造函数仅在AngularJS对HTML文档进行编译时被执行一次。
一旦控制器建立完毕,就意味着scope对象上的业务模型构造完毕,此后就再也不须要控制器了,由于scope对象接管了。
控制器和scope?
<html ng-app=“myApp">
<body ng-init=“foo={name:’hello'}”>
<div ng-controller=“myCtrl"></div>
</body>
</html>
对scope的影响是什么样的呢?
$rootScope: {
foo: {name: ‘hello'}
}
scope: {
prototype: $rootScope,
bar: ...
}
能够看到ng-app指令建立了$rootScope对象,这个时候它仍是一个空对象。
body元素对应的scope对象仍是$rootScope,ng-init指令将foo对象挂到了$rootScope上
div元素又经过ng-controller指令建立了一个新的scope对象,这个对象的原型是$rootScope
由于继承关系,若是在scope中引用foo会指向$rootScope.foo
注意不要在controller中作的事情:
1.DOM操做
2.表单输入的格式化,用form controls
3.输出内容的格式化和过滤,用filter
4.控制器之间的数据共享,另外定义services服务来处理
以上就是上节课的内容解析啦