如何在具有隔离范围的指令上使用 ng-click?
How can I use ng-click on a directive with isolate scope?
我可以让 ng-click 在指令上继承范围时工作,但在隔离时不能。 UPDATE: The point is that I want the click function to be defined as part of the directive... moving the function definition into a different scope is not what I want.
这是具有继承作用域的工作示例:
https://codepen.io/anon/pen/PGBQvj
这是带有隔离作用域的损坏示例;
https://codepen.io/anon/pen/jrpkjp
(单击数字,它们在第一个示例中递增,但在第二个示例中不递增)
一些代码...
HTML
<div ng-app="myApp" ng-controller="baseController">
<my-directive ng-click="hello()" current="current"></my-directive>
</div>
具有继承作用域的指令:
angular.module('myApp', [])
.controller('baseController', function($scope) {
$scope.current = 1;
})
.directive('myDirective', function() {
return {
link: function(scope, element, attrs) {
scope.hello = function() {
scope.current++
};
},
replace: true,
scope: true,
template: '<div><child> <strong>{{ current }}</strong></child></div>'
}
})
.directive('child', function() {
return {
link: function(scope, element, attrs) {
console.log("horeee");
}
}
});
相同的指令,但作用域独立:
angular.module('myApp', [])
.controller('baseController', function($scope) {
$scope.current = 1;
})
.directive('myDirective', function() {
return {
link: function(scope, element, attrs) {
scope.hello = function() {
scope.current++
};
},
replace: true,
scope: {
current:'='
},
template: '<div><child> <strong>{{ current }}</strong></child></div>'
}
})
.directive('child', function() {
return {
link: function(scope, element, attrs) {
console.log("horeee");
}
}
});
使用 isolated 指令,您可以使用 ng-click="$parent.hello()"
而不是 ng-click="hello()"
。很高兴在你的问题中 post 笔。
说明:
当您在一个元素上使用 ng-click
时,它的值 (hello()
) 将相对于它的外部范围进行评估,即示例中控制器的范围。当您创建一个使用非隔离范围的指令时,控制器的范围被传递给 link
函数,并且 hello
在控制器的范围上定义。
// 编辑代码:
angular.module('myApp', [])
.controller('baseController', function($scope) {
$scope.current = 1;
$scope.hello = () => $scope.current ++;
})
.directive('myDirective', function() {
return {
link: function(scope, element, attrs) {
},
replace: true,
scope: {
current:'='
},
template: '<div><child> <strong>{{ current }}</strong></child></div>'
}
})
.directive('child', function() {
return {
link: function(scope, element, attrs) {
console.log("horeee");
}
}
});
给控制器添加hello函数。让它更新 current 的值并将其传递到指令的隔离范围
.controller('baseController', function($scope) {
$scope.current = 1;
$scope.hello = function() {
$scope.current++;
};
})
您需要将对象从控制器传递到指令
将您的 js 更改为
angular.module('myApp', [])
.controller('baseController', function($scope) {
$scope.current = {};
$scope.current.val=1;
})
.directive('myDirective', function() {
return {
link: function(scope, element, attrs) { scope.internalcurrent= scope.current || {};
//scope.internalcurrent.val=1;
scope.internalcurrent.hello = function() {
scope.internalcurrent.val++
};
},
replace: true,
scope: {
current:'='
},
template: '<div><child> <strong>{{ internalcurrent.val }}</strong></child></div>'
}
})
.directive('child', function() {
return {
link: function(scope, element, attrs) {
console.log("horeee");
}
}
});
你的html到
<div ng-app="myApp" ng-controller="baseController">
<my-directive ng-click="hello()" current="current"></my-directive>
</div>
如果您希望在指令中定义点击功能,那么您需要像这样在模板中附加处理程序:
template: '<div ng-click="hello()"><child><strong>{{current}}</strong></child></div>'
当您将处理程序附加到指令声明时,就像在您损坏的示例中一样,您基本上是在告诉 ng-click 您想要在当前范围(控制器的范围)上调用一个函数。这可能看起来不像正在发生的事情,因为在您的工作示例中,您的函数是从 myDirective 中定义的,但它实际上被附加到范围,在这种情况下(工作示例)是控制器的范围。
问题是您正在尝试调用未定义的函数。如果您希望在隔离指令中定义逻辑,则无需传入函数引用。
<my-directive current="current"></my-directive>
你不能在这里传递 ng-click="hello()"
。这是控制器的范围,所以 hello()
未定义。
相反,将 ng-click
事件移动到指令模板
template: '<div ng-click="hello()">
补充一点:
您正在使用指令的 link()
函数。这是为 DOM 操作保留的。相反,在 controller
函数中定义 hello()
。
controller: function ($scope) {
$scope.hello = function() {
$scope.current++
}
},
不过,我认为这里存在一个更大的架构问题。独立指令或组件的要点是封装自身内部的逻辑。它不应该操纵外部状态。在此示例中,您递增一个数字。如果在您的应用程序的另一部分中,您希望减少一个数字怎么办?使用递减逻辑复制指令会产生大量代码重复。
相反,您应该在控制器中定义递增或递减功能,并将其传递给指令。
<my-directive change-number="increment()" current="current"></my-directive>
然后,使用 &
语法将函数引用绑定到指令:
scope: {
current:'=',
changeNumber: '&'
},
并从模板中调用 changeNumber
。这样做非常有利于代码重用。
我可以让 ng-click 在指令上继承范围时工作,但在隔离时不能。 UPDATE: The point is that I want the click function to be defined as part of the directive... moving the function definition into a different scope is not what I want.
这是具有继承作用域的工作示例: https://codepen.io/anon/pen/PGBQvj
这是带有隔离作用域的损坏示例; https://codepen.io/anon/pen/jrpkjp
(单击数字,它们在第一个示例中递增,但在第二个示例中不递增)
一些代码...
HTML
<div ng-app="myApp" ng-controller="baseController">
<my-directive ng-click="hello()" current="current"></my-directive>
</div>
具有继承作用域的指令:
angular.module('myApp', [])
.controller('baseController', function($scope) {
$scope.current = 1;
})
.directive('myDirective', function() {
return {
link: function(scope, element, attrs) {
scope.hello = function() {
scope.current++
};
},
replace: true,
scope: true,
template: '<div><child> <strong>{{ current }}</strong></child></div>'
}
})
.directive('child', function() {
return {
link: function(scope, element, attrs) {
console.log("horeee");
}
}
});
相同的指令,但作用域独立:
angular.module('myApp', [])
.controller('baseController', function($scope) {
$scope.current = 1;
})
.directive('myDirective', function() {
return {
link: function(scope, element, attrs) {
scope.hello = function() {
scope.current++
};
},
replace: true,
scope: {
current:'='
},
template: '<div><child> <strong>{{ current }}</strong></child></div>'
}
})
.directive('child', function() {
return {
link: function(scope, element, attrs) {
console.log("horeee");
}
}
});
使用 isolated 指令,您可以使用 ng-click="$parent.hello()"
而不是 ng-click="hello()"
。很高兴在你的问题中 post 笔。
说明:
当您在一个元素上使用 ng-click
时,它的值 (hello()
) 将相对于它的外部范围进行评估,即示例中控制器的范围。当您创建一个使用非隔离范围的指令时,控制器的范围被传递给 link
函数,并且 hello
在控制器的范围上定义。
// 编辑代码:
angular.module('myApp', [])
.controller('baseController', function($scope) {
$scope.current = 1;
$scope.hello = () => $scope.current ++;
})
.directive('myDirective', function() {
return {
link: function(scope, element, attrs) {
},
replace: true,
scope: {
current:'='
},
template: '<div><child> <strong>{{ current }}</strong></child></div>'
}
})
.directive('child', function() {
return {
link: function(scope, element, attrs) {
console.log("horeee");
}
}
});
给控制器添加hello函数。让它更新 current 的值并将其传递到指令的隔离范围
.controller('baseController', function($scope) {
$scope.current = 1;
$scope.hello = function() {
$scope.current++;
};
})
您需要将对象从控制器传递到指令
将您的 js 更改为
angular.module('myApp', [])
.controller('baseController', function($scope) {
$scope.current = {};
$scope.current.val=1;
})
.directive('myDirective', function() {
return {
link: function(scope, element, attrs) { scope.internalcurrent= scope.current || {};
//scope.internalcurrent.val=1;
scope.internalcurrent.hello = function() {
scope.internalcurrent.val++
};
},
replace: true,
scope: {
current:'='
},
template: '<div><child> <strong>{{ internalcurrent.val }}</strong></child></div>'
}
})
.directive('child', function() {
return {
link: function(scope, element, attrs) {
console.log("horeee");
}
}
});
你的html到
<div ng-app="myApp" ng-controller="baseController">
<my-directive ng-click="hello()" current="current"></my-directive>
</div>
如果您希望在指令中定义点击功能,那么您需要像这样在模板中附加处理程序:
template: '<div ng-click="hello()"><child><strong>{{current}}</strong></child></div>'
当您将处理程序附加到指令声明时,就像在您损坏的示例中一样,您基本上是在告诉 ng-click 您想要在当前范围(控制器的范围)上调用一个函数。这可能看起来不像正在发生的事情,因为在您的工作示例中,您的函数是从 myDirective 中定义的,但它实际上被附加到范围,在这种情况下(工作示例)是控制器的范围。
问题是您正在尝试调用未定义的函数。如果您希望在隔离指令中定义逻辑,则无需传入函数引用。
<my-directive current="current"></my-directive>
你不能在这里传递 ng-click="hello()"
。这是控制器的范围,所以 hello()
未定义。
相反,将 ng-click
事件移动到指令模板
template: '<div ng-click="hello()">
补充一点:
您正在使用指令的 link()
函数。这是为 DOM 操作保留的。相反,在 controller
函数中定义 hello()
。
controller: function ($scope) {
$scope.hello = function() {
$scope.current++
}
},
不过,我认为这里存在一个更大的架构问题。独立指令或组件的要点是封装自身内部的逻辑。它不应该操纵外部状态。在此示例中,您递增一个数字。如果在您的应用程序的另一部分中,您希望减少一个数字怎么办?使用递减逻辑复制指令会产生大量代码重复。
相反,您应该在控制器中定义递增或递减功能,并将其传递给指令。
<my-directive change-number="increment()" current="current"></my-directive>
然后,使用 &
语法将函数引用绑定到指令:
scope: {
current:'=',
changeNumber: '&'
},
并从模板中调用 changeNumber
。这样做非常有利于代码重用。