该指令在父作用域和子作用域中重命名的“本地”变量之间提供 2 路数据绑定。它可以与其他指令结合使用,例如ng-include
出色的模板可重用性。需要 AngularJS 1.2.x
标记
<div with-locals locals-cars="allCars | onlyNew"></div>
这是怎么回事:
- 这基本上是
ngInclude
指令的扩展,允许您从父范围传递重命名的变量。ngInclude
根本不需要,但该指令旨在与它很好地配合使用。
- 您可以附加任意数量的
locals-*
属性,这些属性都将作为 Angular 表达式为您解析和观察。
- 这些表达式可用于包含的部分,作为
$scope.locals
对象的属性附加。
- 在上面的示例中,
locals-cars="..."
定义了一个可用作 的表达式$scope.locals.cars
。
- 类似于如何
data-cars="..."
通过 jQuery 使用属性.data().cars
指令
编辑我已经重构以利用(并独立于)本机ngInclude
指令,并将一些计算移到编译函数中以提高效率。
angular.module('withLocals', [])
.directive('withLocals', function($parse) {
return {
scope: true,
compile: function(element, attributes, transclusion) {
// for each attribute that matches locals-* (camelcased to locals[A-Z0-9]),
// capture the "key" intended for the local variable so that we can later
// map it into $scope.locals (in the linking function below)
var mapLocalsToParentExp = {};
for (attr in attributes) {
if (attributes.hasOwnProperty(attr) && /^locals[A-Z0-9]/.test(attr)) {
var localKey = attr.slice(6);
localKey = localKey[0].toLowerCase() + localKey.slice(1);
mapLocalsToParentExp[localKey] = attributes[attr];
}
}
var updateParentValueFunction = function($scope, localKey) {
// Find the $parent scope that initialized this directive.
// Important in cases where controllers have caused this $scope to be deeply nested inside the original parent
var $parent = $scope.$parent;
while (!$parent.hasOwnProperty(mapLocalsToParentExp[localKey])) {
$parent = $parent.$parent;
}
return function(newValue) {
$parse(mapLocalsToParentExp[localKey]).assign($parent, newValue);
}
};
return {
pre: function($scope, $element, $attributes) {
// setup `$scope.locals` hash so that we can map expressions
// from the parent scope into it.
$scope.locals = {};
for (localKey in mapLocalsToParentExp) {
// For each local key, $watch the provided expression and update
// the $scope.locals hash (i.e. attribute `locals-cars` has key
// `cars` and the $watch()ed value maps to `$scope.locals.cars`)
$scope.$watch(
mapLocalsToParentExp[localKey],
function(localKey) {
return function(newValue, oldValue) {
$scope.locals[localKey] = newValue;
};
}(localKey),
true
);
// Also watch the local value and propagate any changes
// back up to the parent scope.
var parsedGetter = $parse(mapLocalsToParentExp[localKey]);
if (parsedGetter.assign) {
$scope.$watch('locals.'+localKey, updateParentValueFunction($scope, localKey));
}
}
}
};
}
};
});