1.背景介绍
AngularJs是一个用于设计动态web应用的结构框架,使得开发现代的单一页面应用程序变得更加容易。而且 能够简化我们的工作流程, 让我们只专心于业务逻辑和数据的处理。$scope $rootScope $watch 和 $state就是里面的 几个方法,今天着重跟大家讨论一下这几个方法。
2.知识剖析
$scope——Scope(作用域) 是应用在 HTML (视图) 和 JavaScript (控制器)之间的纽带。Scope 是一 个对象,有可用的方法和属性。 Scope 可应用在视图和控制器上。$scope 的使用贯穿整个 Angular App 应用,它与数 据模型相关联,同时也是表达式执行的上下文。 有了 $scope 就在视图和控制器之间建立了一个通道,基于作用域视图在 修改数据时会立刻更新 $scope, 同样的 $scope发生改变时也会立刻重新渲染视图。
$scope 的生命周期
- $scope 的生命周期有4个阶段:
- 创建:控制器或者指令创建时, Angular 会使用 $injector 创建一个新的作用域,然后在控制器或指令运行时, 将作用域传递进去。
- 链接:Angular 启动后会将所有 $scope 对象附加或者说链接到视图上,所有创建 $scope 对象的函数也会被附 加到视图上。 这些作用域将会注册当 Angular 上下文发生变化时需要运行的函数.也就是 $watch 函数, Angular 通过这些函数或者何时开始事件循环。
- 更新:一旦事件循环开始运行,就会开始执行自己的脏值检测.一旦检测到变化,就会触发 $scope 上指定的回调函数。
- 销毁:通常来讲如果一个 $scope 在视图中不再需要, 需要对其进行清理。
$rootscope
$rootscope——每一个Angular应用都会有一个 $rootScope。这个 $rootScope 是最顶级的scope,它 对应着含有 ng-app 指令属性的那个DOM元素。 如果页面上没有明确设定 $scope ,Angular 就会把数据和函数都绑定 到这里。Angular 应用启动并生成视图时,会将根 ng-app 元素与 $rootScope 进行绑定.$rootScope 是所有 $scope 的 最上层对象, 可以理解为一个 Angular 应用中得全局作用域对象。
$watch
相信使用过angularjs的同学都知道,ng中有个比较重要的特点,叫做双向绑定,那么这个双向绑定是如何 实现的呢? 当我们在对绑定的name属性进行修改的时候,angular内部的$digest循环级会执行一次, 他执行的内容是检 查我们的 $scope作用域的内容与上次执行$digest循环的时候是否有变化,若有变化就执行$watch()方法绑定的处理函数。 从而 达到了监听作用域属性的效果。
$watch的几个参数
- watchExpression;需要监控的表达式;
- listener,处理函数,函数参数如下 function(newValue,oldValue, scope);
- objectEquality,是否深度监听,如果设置为true,它告诉Angular检查所监控的对象中每一个属性的变化. 如果你希 望监控数组的个别元素或者对象的属性而不是一个普通的值, 那么你应该使用它。
$state
在ajax技术发展普及之后,因为其不会留下历史记录方便浏览器访问和对于seo不友好的特点,一个新技术 应运而生: 路由,$state就是路由中的一项服务。
$state.go()
$state.go()方法可以产生与a链接一样的效果,可以将此方法绑定给一个button按钮, 然后在按钮的点击 事件中执行 $state.go(),就可以跳转到相应的页面。
$stateparams
$stateParams是一个对象,包含 url 中每个参数的键/值。$stateParams可以为控制器或者服务提供 url 的各个部分。 注意:$stateParams必须与一个控制器相关,并且$stateParams中的“键/值”也必须事先在那个控制器的url属性中有定义。
3.常见问题
$watch的深度监听是什么?
$watch的深度监听有什么优缺点?
4.解决方案
$watch的深度监听是什么?
$watch在对待原始类型和引用类型会有不同的处理方式,这就要首先说一说$watch函数的第三个参数。在前面的例子中, 我们知道,$watch函数有接收两个参数,第一个参数是需要监视的对象,第二个参数是在监视对象发生变化时需要调用 的函数, 实际上$watch还有第三个参数,它在默认情况下是false。在默认情况下,即不显示指明第三个参数或者将其 指明为false时, 我们进行的监视叫做“引用监视”。引用监视的原词的“reference watch”,它的意思是只要监视的 对象引用没有发生变化, 就不算它发生了变化。如果我们将$watch的第三个变量设置为true,那么此时我们进行的监视 叫做“全等监视”,原词是“equality watch”。
$watch的深度监听有什么优缺点?
前面我们说到,只要$watch的对象有一点风吹草动,watch的深度监听马上就跳出来; 既然全 等监视这么好,那么我们为什么不直接用全等监视呢?当然,任何事情都有好的坏的两个方面,全等监视固然是好, 但 是它在运行时需要先遍历整个监视对象,然后在每次$digest(脏检查机制)之前使用angular.copy()将整个对象深拷贝一遍然后在运行 之后用angular.equal()将前后的对象进行对比。对性能优化来说这可不是很友好。
5.编码实战
6.扩展思考
$watch脏检测原理
scope通过$watch方法向this. watchers数组中添加watcher对象每当$digest循环被触发时, 它会遍历watchers数组中添加watcher对象(包含watchFn, listenerFn, valueEq, last 四个属性)。每当$digest循环被 触发时,它会遍历watchers数组,执行watcher中的watchFn,获取当前scope上某属性的值(一个watcher对应scope上一 个被监听属性),然后去同watcher中的last(上一次的值)做比较,若两值不相等,就执行listenerFn。
7.参考文献
参考资料:http://www.cnblogs.com/sitemanager/p/3513827.html
—— 『AngularJS』理解$Scope
参考资料:https://www.jianshu.com/p/3398f1d19320
—— 关于angularJS的$watch的 一些小用法
参考资料:http://yuankeqiang.lofter.com/post/8de51_1454f93
—— angularJS中的$watch方法监听作用域
8.更多讨论
怎么定义或修改$rootScope作用域的属性和方法?
$stateParams如果没有用url接收会怎样?
9.互动提问
$rootScope是否可以替代$scope?
答:是可以替代的,但是不建议这样用,因为这样使用就相当于js中的全局变量,定义过多会导致全局污染。
$stateParams如果没有用url接收会怎样?
答;如果没有在url里面接收,会导致再次提取$stateParams中的数据的时候,会找不到该数据;$stateParams对象中根本就没有该属性。
$state.params和$stateParams的区别?
答:$state.params里的params是自己定义的,可以写成listParams,optionparams等
$stateParams是angular定义的固定写法;