今天,我在查看ngOptions.js来源时遇到了这个问题:
getWatchables: $parse(valuesFn, function(values) {
// Create a collection of things that we would like to watch (watchedArray)
// so that they can all be watched using a single $watchCollection
// that only runs the handler once if anything changes
var watchedArray = [];
values = values || [];
Object.keys(values).forEach(function getWatchable(key) {
var locals = getLocals(values[key], key);
var label = displayFn(scope, locals);
var selectValue = getTrackByValue(values[key], locals);
watchedArray.push(selectValue);
watchedArray.push(label);
});
return watchedArray;
}),
但是$parse的官方文档没有指定任何第二个参数。
它做了什么?
答案 0 :(得分:2)
<强>来源强>
V1.3.4:
function addInterceptor(parsedExpression, interceptorFn) {
if (!interceptorFn) return parsedExpression;
var watchDelegate = parsedExpression.$$watchDelegate;
var regularWatch =
watchDelegate !== oneTimeLiteralWatchDelegate &&
watchDelegate !== oneTimeWatchDelegate;
var fn = regularWatch ? function regularInterceptedExpression(scope, locals) {
var value = parsedExpression(scope, locals);
return interceptorFn(value, scope, locals);
} : function oneTimeInterceptedExpression(scope, locals) {
var value = parsedExpression(scope, locals);
var result = interceptorFn(value, scope, locals);
// we only return the interceptor's result if the
// initial value is defined (for bind-once)
return isDefined(value) ? result : value;
};
// Propagate $$watchDelegates other then inputsWatchDelegate
if (parsedExpression.$$watchDelegate &&
parsedExpression.$$watchDelegate !== inputsWatchDelegate) {
fn.$$watchDelegate = parsedExpression.$$watchDelegate;
} else if (!interceptorFn.$stateful) {
// If there is an interceptor, but no watchDelegate then treat the interceptor like
// we treat filters - it is assumed to be a pure function unless flagged with $stateful
fn.$$watchDelegate = inputsWatchDelegate;
fn.inputs = [parsedExpression];
}
return fn;
}
根据上面的示例和angularjs的来源,第二个参数允许您将 transform-like 逻辑应用于解析结果。
查看https://github.com/angular/angular.js/blob/master/src/ng/directive/ngOptions.js#L461:
// We will re-render the option elements if the option values or labels change
scope.$watchCollection(ngOptions.getWatchables, updateOptions);
似乎,它用于为ngOptions来源中的手表提供单一方式。它会在更改名称和/或标签时触发。如果不使用,手表只能用于更换标签或仅用于更改价值,而不是两者兼而有之。
角度代码中使用的其他样本
1。观看ng-bind
var ngBindHtmlWatch = $parse(tAttrs.ngBindHtml, function getStringValue(value) {
return (value || '').toString();
});
这里我们构建一个基于$ parse值转换为字符串的监视器。似乎在$ digest周期中进行了更好,更简单的比较。
2。手表在&#39; =&#39; -scoped指令参数
var parentValueWatch = function parentValueWatch(parentValue) {
if (!compare(parentValue, isolateBindingContext[scopeName])) {
// we are out of sync and need to copy
if (!compare(parentValue, lastValue)) {
// parent changed and it has precedence
isolateBindingContext[scopeName] = parentValue;
} else {
// if the parent can be assigned then do so
parentSet(scope, parentValue = isolateBindingContext[scopeName]);
}
}
return lastValue = parentValue;
};
如您所见,我们只是根据脏检查保持范围值同步。这就是为什么我们需要第二个$ digest-cycle来触发指令的内部监视。
<强>摘要强>
似乎它是一种从繁重的东西转变为简单的东西的方式,在$ digest-cycle中,简单的=
可以与之形成对比。如果我们触发手表,我们需要得出结论。
它也可以用作为手表设置通用逻辑的方法。它允许编写一次,并在我们需要$ parsed值时用于所有情况。