调试时抓取作用域:
1、右键选取审查元素,调出 debugger(或按 F12)
2、调试器允许用变量 $0 来获取当前选取的元素
3、在 console 中执行 angular.element($0).scope() 或直接输入 $scope 即可看到需要查询的当前 DOM 元素节点绑定的作用域
基于作用域的事件传播:
1、broadcasted:从父级作用域广播至子级作用域
2、emitted:从子级作用域往上发射到父级作用域
补充:
1、$emit:该服务贯穿作用域发出一个向上的事件,并通知那些注册在 rootScope.Scope 上的监听器;
起始于 emit 被启动的地方,向上传播;若有一个监听器接受了这个事件,则会停止继续向上传播
2、$broadcast:与 $emit 的方向相反,且监听器接受到通知后并不会注销事件,而是继续向下传播
3、$on:该服务监听指定类型的事件,获取从 emit 或 broadcast 发布的事件
浏览器接受一个事件的标准工作流程:
接收事件 ==》触发回调 ==》回调执行结束返回 ==》浏览器重绘 DOM ==》浏览器返回等待下一个事件
当浏览器的控制权跑到原生的 Javascript 中去时,则执行上下文就发生在 Angular 的上下文之外 ==》Angular 无法得知数据模型的任何改变
==》使用 $apply 方法让上下文执行环境重新进入 Angular 的上下文中($scope.$apply())==》数据模型改变从而被识别
在计算完表达式后,$apply() 方法执行 Angular 的 $digest 阶段(可认为是必要的缓冲阶段
==》scope 检查所有通过 $watch() 监听的表达式(或别的数据)并将其与它们之前的值进行比较《== 脏值检查(dirty checking)
注:$watch() 的监测是异步的,需要等 $digest 阶段跑完才调用
scope 生命周期拆解:
1、创建期:root scope 是在应用程序启动时由 $injector 创建的;另外,在指令的模板链接阶段(template linking),指令会创建一些新的子级 scope
2、注册期:在模板链接阶段,指令会往作用域中注册监听器,而且不止一个,这些 $watch 用来监测数据模型的更新并将更新值传给 DOM
3、数据模型变化:数据模型的变化应在 Angular 的监测之下($scope.$apply()),对于 Angular 本身的 API 不用显式地调用该函数
4、数据模型变化监测:把数据模型变化 $apply 后,Angular 开始进入 $digest 轮循(调用 $digest() 方法),从父级到子级依次执行,
若监听到自己负责地数据模型有变化,则调用 $watch
5、销毁作用域:当子级作用域不再需要的时候,这时创建它们的就会负责把它们回收或者销毁;可通过 scope.$destroy() 显式销毁或直接隐式销毁;
之后 $digest() 方法就不会继续往子级作用域传播了