没有合适的资源?快使用搜索试试~ 我知道了~
温馨提示
简介 在ng的生态中scope处于一个核心的地位,ng对外宣称的双向绑定的底层其实就是scope实现的,本章主要对scope的watch机制、继承性以及事件的实现作下分析。 监听 1. $watch 1.1 使用 // $watch: function(watchExp, listener, objectEquality) var unwatch = $scope.$watch('aa', function () {}, isEqual); 使用过angular的会经常这上面这样的代码,俗称“手动”添加监听,其他的一些都是通过插值或者directive自动地添加监听,但是原理上都一样。 1.
资源推荐
资源详情
资源评论
angularjs 源码解析之源码解析之scope
简介简介
在ng的生态中scope处于一个核心的地位,ng对外宣称的双向绑定的底层其实就是scope实现的,本章主要对scope的watch机
制、继承性以及事件的实现作下分析。
监听监听
1. $watch
1.1 使用
// $watch: function(watchExp, listener, objectEquality)
var unwatch = $scope.$watch('aa', function () {}, isEqual);
使用过angular的会经常这上面这样的代码,俗称“手动”添加监听,其他的一些都是通过插值或者directive自动地添加监听,但
是原理上都一样。
1.2 源码分析
function(watchExp, listener, objectEquality) {
var scope = this,
// 将可能的字符串编译成fn
get = compileToFn(watchExp, 'watch'),
array = scope.$$watchers,
watcher = {
fn: listener,
last: initWatchVal, // 上次值记录,方便下次比较
get: get,
exp: watchExp,
eq: !!objectEquality // 配置是引用比较还是值比较
};
lastDirtyWatch = null;
if (!isFunction(listener)) {
var listenFn = compileToFn(listener || noop, 'listener');
watcher.fn = function(newVal, oldVal, scope) {listenFn(scope);};
}
if (!array) {
array = scope.$$watchers = [];
}
// 之所以使用unshift不是push是因为在 $digest 中watchers循环是从后开始
// 为了使得新加入的watcher也能在当次循环中执行所以放到队列最前
array.unshift(watcher);
// 返回unwatchFn, 取消监听
return function deregisterWatch() {
arrayRemove(array, watcher);
lastDirtyWatch = null;
};
}
从代码看 $watch 还是比较简单,主要就是将 watcher 保存到 $$watchers 数组中
2. $digest
当 scope 的值发生改变后,scope是不会自己去执行每个watcher的listenerFn,必须要有个通知,而发送这个通知的就是
$digest
2.1 源码分析
整个 $digest 的源码差不多100行,主体逻辑集中在【脏值检查循环】(dirty check loop) 中, 循环后也有些次要的代码,如
postDigestQueue 的处理等就不作详细分析了。
脏值检查循环,意思就是说只要还有一个 watcher 的值存在更新那么就要运行一轮检查,直到没有值更新为止,当然为了减少
不必要的检查作了一些优化。
代码:
// 进入$digest循环打上标记,防止重复进入
beginPhase('$digest');
lastDirtyWatch = null;
// 脏值检查循环开始
do {
dirty = false;
current = target;
// asyncQueue 循环省略
traverseScopesLoop:
do {
if ((watchers = current.$$watchers)) {
length = watchers.length;
while (length--) {
try {
watch = watchers[length];
if (watch) {
// 作更新判断,是否有值更新,分解如下
// value = watch.get(current), last = watch.last
// value !== last 如果成立,则判断是否需要作值判断 watch.eq?equals(value, last)
// 如果不是值相等判断,则判断 NaN的情况,即 NaN !== NaN
if ((value = watch.get(current)) !== (last = watch.last) &&
!(watch.eq
? equals(value, last)
: (typeof value === 'number' && typeof last === 'number'
&& isNaN(value) && isNaN(last)))) {
dirty = true;
// 记录这个循环中哪个watch发生改变
lastDirtyWatch = watch;
// 缓存last值
watch.last = watch.eq ? copy(value, null) : value;
// 执行listenerFn(newValue, lastValue, scope)
// 如果第一次执行,那么 lastValue 也设置为newValue
watch.fn(value, ((last === initWatchVal) ? value : last), current);
// ... watchLog 省略
if (watch.get.$$unwatch) stableWatchesCandidates.push({watch: watch, array: watchers});
}
// 这边就是减少watcher的优化
// 如果上个循环最后一个更新的watch没有改变,即本轮也没有新的有更新的watch
// 那么说明整个watches已经稳定不会有更新,本轮循环就此结束,剩下的watch就不用检查了
else if (watch === lastDirtyWatch) {
dirty = false;
break traverseScopesLoop;
}
}
} catch (e) {
clearPhase();
$exceptionHandler(e);
}
}
}
// 这段有点绕,其实就是实现深度优先遍历
// A->[B->D,C->E] // 执行顺序 A,B,D,C,E
// 每次优先获取第一个child,如果没有那么获取nextSibling兄弟,如果连兄弟都没了,那么后退到上一层并且判断该层是否有
兄弟,没有的话继续上退,直到退到开始的scope,这时next==null,所以会退出scopes的循环
if (!(next = (current.$$childHead ||
(current !== target && current.$$nextSibling)))) {
while(current !== target && !(next = current.$$nextSibling)) {
current = current.$parent;
}
}
剩余10页未读,继续阅读
资源评论
weixin_38694336
- 粉丝: 3
- 资源: 951
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
最新资源
- 基于MINiscope光子的钙成像信号提取管道.zip
- 基于暗通道先验的单幅图像去雾的MATLAB实现.zip
- 基于OFDM的功率域NOMA系统的MATLAB实现.zip
- 1992-2023年各省工业增加值数据(无缺失).xls
- chromedriver-linux64-117.0.5931.0.zip
- 基于Peter Corkes机器人工具箱的协作控制和操作的matlab脚本,并修复了RTB 1031的一些错误.zip
- 基于导频信号LS信道估计的QPSK和OFDM调制卫星通信系统的误码率MATLAB仿真建模.zip
- 基于反馈控制参数优化的无人机群导航编队控制中存在障碍物时沉降时间最小化方法在MATLAB中设计并仿真了一个群导航模型.zip
- 基于轨迹集的扩展目标PMBM跟踪器的MATLAB实现.zip
- 基于间接卡尔曼滤波的IMU与GPS融合MATLAB仿真IMU与GPS数据由仿真生成.zip
- 基于模拟退火SA的车辆路径问题VRP.zip
- 基于神经网络的手写体字符识别系统是利用MATLAB神经网络和图像处理工具箱开发的,该系统是利用现有的预处理和特征提取等.zip
- 基于小波变换的信号突变点检测MATLAB实现.zip
- 基于误差状态卡尔曼滤波的gps定位传感器融合MATLAB实现.zip
- 基于网格快速slam的rablacwelzed粒子滤波的MatLab实现.zip
- 极化合成孔径雷达极化定标和校准 相关Some work I did during my graduate studie.zip
资源上传下载、课程学习等过程中有任何疑问或建议,欢迎提出宝贵意见哦~我们会及时处理!
点击此处反馈
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功