将参数传递给具有隔离范围的嵌套指令
Passing params to nested directives with isolated scope
我在 MainCtrl
中有一个对象 data
。该对象用于将数据传递给指令 first-directive
和 second-directive
。在这两种情况下都需要双数据绑定。
对于first-directive
,我传递了完整的对象data
,但是对于second-directive
,我想传递numbers
对象(scope.numbers = scope.dataFirst.numbers
)。
问题:
当我执行 <div second-directive="dataFirst.numbers"></div>
时,我检查 dataSecond
是否是一个对象,它 returns true
.
但是当我执行 <div second-directive="numbers"></div>
并检查 dataSecond
是否是一个对象时,它 returns false
.
在这两种情况下,如果我执行 console.log(scope)
,则会显示 scope.dataSecond
属性。
问题:
为什么会发生这种情况,将参数传递给指令的正确方法是什么?
编辑:
这个想法是制作可重用的指令,这意味着它们不能依赖于其他指令。
angular.module('app',[])
.controller('MainCtrl', function($scope) {
$scope.data = {
numbers: {
n1: 'one',
n2: 'two'
},
letters: {
a: 'A',
b: 'B'
}
}
})
.directive('firstDirective', function () {
return {
template: '<div class="first-directive">\
<h2>First Directive</h2>\
{{dataFirst}}\
<div second-directive="dataFirst.numbers"></div>\
<div second-directive="numbers"></div>\
</div>',
replace: true,
restrict: 'A',
scope: {
dataFirst: '=firstDirective'
},
link: function postLink(scope, element, attrs) {
console.log('first directive')
console.log(scope)
scope.numbers = scope.dataFirst.numbers;
}
};
})
.directive('secondDirective', function () {
return {
template: '<div class="second-directive">\
<h2>Second Directive</h2>\
{{dataSecond}}\
<div class="is-obj">is an object: {{isObj}}</div>\
</div>',
replace: true,
restrict: 'A',
scope: {
dataSecond: '=secondDirective'
},
link: function postLink(scope, element, attrs) {
console.log('second directive');
console.log(scope)
// <div second-directive="XXXX"></div>
// if 'numbers' returns undefined
// if 'dataFirst.numbers' returns the object
console.log(scope.dataSecond);
scope.isObj = false;
if(angular.isObject(scope.dataSecond)){
scope.isObj = true;
}
}
};
});
h2 {
padding: 0;
margin: 0;
}
.first-directive {
background: #98FFDA;
color: black;
padding: 10px;
}
.second-directive {
background: #FFA763;
color: white;
padding: 10px;
}
.is-obj {
background: blue;
}
<!DOCTYPE html>
<html ng-app="app">
<head>
<meta charset="utf-8" />
<title>AngularJS Plunker</title>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
</head>
<body ng-controller="MainCtrl">
<h2>MainCtrl</h2>
{{data}}
<div first-directive="data">
</div>
<div second-directive="data">
</div>
</body>
</html>
我的解决方案是让第二个指令从第一个指令继承数据对象属性。
angular.module('app', [])
.controller('MainCtrl', function($scope) {
$scope.data = {
numbers: {
n1: 'one',
n2: 'two'
},
letters: {
a: 'A',
b: 'B'
}
}
})
.directive('firstDirective', function() {
return {
template: '<div class="first-directive">\
<h2>First Directive</h2>\
{{dataFirst}}\
<div second-directive></div>\
<div second-directive></div>\
</div>',
replace: true,
restrict: 'A',
scope: {
dataFirst: '=firstDirective'
},
controller: function firstDirectiveController($scope) {
return $scope;
},
link: function postLink(scope, element, attrs) {
console.log('first directive')
console.log(scope)
scope.numbers = scope.dataFirst.numbers;
}
};
})
.directive('secondDirective', function() {
return {
template: '<div class="second-directive">\
<h2>Second Directive</h2>\
{{dataSecond}}\
<div class="is-obj">is an object: {{isObj}}</div>\
</div>',
replace: true,
require: '^firstDirective',
link: function postLink(scope, iElement, iAttrs, firstDirectiveController) {
console.log('second directive');
console.log(firstDirectiveController.dataFirst.numbers);
scope.dataSecond = firstDirectiveController.dataFirst.numbers;
scope.isObj = false;
if (angular.isObject(scope.dataSecond)) {
scope.isObj = true;
}
}
};
});
h2 {
padding: 0;
margin: 0;
}
.first-directive {
background: #98FFDA;
color: black;
padding: 10px;
}
.second-directive {
background: #FFA763;
color: white;
padding: 10px;
}
.is-obj {
background: blue;
}
<!DOCTYPE html>
<html ng-app="app">
<head>
<meta charset="utf-8" />
<title>AngularJS Plunker</title>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<link rel="stylesheet" href="style.css">
<script src="script.js"></script>
</head>
<body ng-controller="MainCtrl">
<h2>MainCtrl</h2>
{{data}}
<div first-directive="data">
</div>
</body>
</html>
我将重复之前其他人所说的话 - firstDirective
的 link
函数是 post-link 函数 运行s 在 secondDirective
的 link
函数之后 [=15] =] 尚未分配对象 scope.dataFirst.numbers
.
但是,通过 require
将两个指令紧密耦合的解决方案对我来说似乎不是最佳选择。
相反,要确保在 inner/child 指令 运行(如本例中的 secondDirective
)之前在父级中正确分配范围 属性在 firstDirective
中使用 pre-link 函数(而不是 post-link)
link: {
pre: function prelink(scope){
console.log('first directive')
console.log(scope)
scope.numbers = scope.dataFirst.numbers;
}
}
我在 MainCtrl
中有一个对象 data
。该对象用于将数据传递给指令 first-directive
和 second-directive
。在这两种情况下都需要双数据绑定。
对于first-directive
,我传递了完整的对象data
,但是对于second-directive
,我想传递numbers
对象(scope.numbers = scope.dataFirst.numbers
)。
问题:
当我执行 <div second-directive="dataFirst.numbers"></div>
时,我检查 dataSecond
是否是一个对象,它 returns true
.
但是当我执行 <div second-directive="numbers"></div>
并检查 dataSecond
是否是一个对象时,它 returns false
.
在这两种情况下,如果我执行 console.log(scope)
,则会显示 scope.dataSecond
属性。
问题:
为什么会发生这种情况,将参数传递给指令的正确方法是什么?
编辑: 这个想法是制作可重用的指令,这意味着它们不能依赖于其他指令。
angular.module('app',[])
.controller('MainCtrl', function($scope) {
$scope.data = {
numbers: {
n1: 'one',
n2: 'two'
},
letters: {
a: 'A',
b: 'B'
}
}
})
.directive('firstDirective', function () {
return {
template: '<div class="first-directive">\
<h2>First Directive</h2>\
{{dataFirst}}\
<div second-directive="dataFirst.numbers"></div>\
<div second-directive="numbers"></div>\
</div>',
replace: true,
restrict: 'A',
scope: {
dataFirst: '=firstDirective'
},
link: function postLink(scope, element, attrs) {
console.log('first directive')
console.log(scope)
scope.numbers = scope.dataFirst.numbers;
}
};
})
.directive('secondDirective', function () {
return {
template: '<div class="second-directive">\
<h2>Second Directive</h2>\
{{dataSecond}}\
<div class="is-obj">is an object: {{isObj}}</div>\
</div>',
replace: true,
restrict: 'A',
scope: {
dataSecond: '=secondDirective'
},
link: function postLink(scope, element, attrs) {
console.log('second directive');
console.log(scope)
// <div second-directive="XXXX"></div>
// if 'numbers' returns undefined
// if 'dataFirst.numbers' returns the object
console.log(scope.dataSecond);
scope.isObj = false;
if(angular.isObject(scope.dataSecond)){
scope.isObj = true;
}
}
};
});
h2 {
padding: 0;
margin: 0;
}
.first-directive {
background: #98FFDA;
color: black;
padding: 10px;
}
.second-directive {
background: #FFA763;
color: white;
padding: 10px;
}
.is-obj {
background: blue;
}
<!DOCTYPE html>
<html ng-app="app">
<head>
<meta charset="utf-8" />
<title>AngularJS Plunker</title>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
</head>
<body ng-controller="MainCtrl">
<h2>MainCtrl</h2>
{{data}}
<div first-directive="data">
</div>
<div second-directive="data">
</div>
</body>
</html>
我的解决方案是让第二个指令从第一个指令继承数据对象属性。
angular.module('app', [])
.controller('MainCtrl', function($scope) {
$scope.data = {
numbers: {
n1: 'one',
n2: 'two'
},
letters: {
a: 'A',
b: 'B'
}
}
})
.directive('firstDirective', function() {
return {
template: '<div class="first-directive">\
<h2>First Directive</h2>\
{{dataFirst}}\
<div second-directive></div>\
<div second-directive></div>\
</div>',
replace: true,
restrict: 'A',
scope: {
dataFirst: '=firstDirective'
},
controller: function firstDirectiveController($scope) {
return $scope;
},
link: function postLink(scope, element, attrs) {
console.log('first directive')
console.log(scope)
scope.numbers = scope.dataFirst.numbers;
}
};
})
.directive('secondDirective', function() {
return {
template: '<div class="second-directive">\
<h2>Second Directive</h2>\
{{dataSecond}}\
<div class="is-obj">is an object: {{isObj}}</div>\
</div>',
replace: true,
require: '^firstDirective',
link: function postLink(scope, iElement, iAttrs, firstDirectiveController) {
console.log('second directive');
console.log(firstDirectiveController.dataFirst.numbers);
scope.dataSecond = firstDirectiveController.dataFirst.numbers;
scope.isObj = false;
if (angular.isObject(scope.dataSecond)) {
scope.isObj = true;
}
}
};
});
h2 {
padding: 0;
margin: 0;
}
.first-directive {
background: #98FFDA;
color: black;
padding: 10px;
}
.second-directive {
background: #FFA763;
color: white;
padding: 10px;
}
.is-obj {
background: blue;
}
<!DOCTYPE html>
<html ng-app="app">
<head>
<meta charset="utf-8" />
<title>AngularJS Plunker</title>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<link rel="stylesheet" href="style.css">
<script src="script.js"></script>
</head>
<body ng-controller="MainCtrl">
<h2>MainCtrl</h2>
{{data}}
<div first-directive="data">
</div>
</body>
</html>
我将重复之前其他人所说的话 - firstDirective
的 link
函数是 post-link 函数 运行s 在 secondDirective
的 link
函数之后 [=15] =] 尚未分配对象 scope.dataFirst.numbers
.
但是,通过 require
将两个指令紧密耦合的解决方案对我来说似乎不是最佳选择。
相反,要确保在 inner/child 指令 运行(如本例中的 secondDirective
)之前在父级中正确分配范围 属性在 firstDirective
中使用 pre-link 函数(而不是 post-link)
link: {
pre: function prelink(scope){
console.log('first directive')
console.log(scope)
scope.numbers = scope.dataFirst.numbers;
}
}