Angular 具有独立作用域和内部控制器的 JS 指令
Angular JS directives with isolate scopes and internal controllers
我已经有一段时间没有接触 angular js 了,当我写的时候,我们使用了一种带有 typescript 的风格,这对我来说非常简单。现在想写vanilla angular js 感觉有点乱
问题:
我有一个在其隔离范围内有几个变量的指令,我基本上想绑定到这个在每个 <ul>
内部产生的指令到一个点击事件。我尝试在 ng-click 上直接绑定一个函数,并使用 link 元素 e.t.c。单击绑定,但似乎我做错了什么,因为第一种方式没有任何反应,第二种方式未定义双向绑定变量。
这里是:
https://plnkr.co/edit/OOBMs8pYONLjUE9lQXla?p=preview
activity-header.html
<div>
<h4>
Activity Name: {{activity.activity_name}}
</h4>
<h6>
Activity Start Date: {{activity.activity_start_date}}
</h6>
<h6>
Activity End Date: {{activity.activity_end_date}}
</h6>
<h6>
Participants: {{activity.participants}}
</h6>
</div>
activity-header.js
var app = angular.module('mainApp');
/*
app.controller('activityHeaderCtrl', ['$scope', function($scope) {
$scope.activity='';
$scope.msg='';
$scope.check = function() {
alert($scope.msg);
};
}]);
*/
app.directive('activityHeader', function() {
return {
restrict: 'AE',
templateUrl: 'activity-header.html',
controller: ['$scope', Controller],
scope: {
activity:'=',
msg:'='
},
link: function($scope, $element, attrs) {
$element.bind('click', function($scope) {
alert($scope.msg);
})}
};
function Controller($scope) {
$scope.check = function() {
alert($scope.msg);
};
}
});
index.html
<html ng-app="mainApp">
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.3.14/angular.min.js"></script>
<script src="script-main.js"></script>
<script src="activity-header.js"></script>
<body>
<div ng-controller="ctrl">
<h1>
Major Bla bla System
</h1>
<ul>
<li ng-repeat="x in events">
<div activity-header activity="x" msg="greetingsfriend" ng-click="check()"></div>
</li>
</ul>
<h6>
Beta v.0.2
</h6>
</div>
</body>
</html>
脚本-main.js
var app = angular.module('mainApp', []);
app.controller('ctrl', function ($scope) {
//$scope.events = ["Elections", "Protest", "Martial Law", "X-mas Celebration"];
$scope.events = [
{"activity_name": "Elections", "activity_start_date": "31/12/2014", "activity_end_date": "31/12/2015", "participants": "1453"},
{"activity_name": "Martial Law", "activity_start_date": "31/12/2014", "activity_end_date": "31/12/2015", "participants": "1821"},
{"activity_name": "Protest", "activity_start_date": "31/12/2014", "activity_end_date": "31/12/2015", "participants": "1940"},
{"activity_name": "X-mas Celebration", "activity_start_date": "31/12/2014", "activity_end_date": "31/12/2015", "participants": "2009"}
];
$scope.salute = function () {
alert('hello there');
};
});
(顺便说一句,我使用的是 Mozilla Firefox,否则我必须将其托管在 node.js 上以实现同源策略,不知道如何在 chrome/ Internet Explorer).
Any idea on how to handle the click?
您的问题是您使用 $scope
作为点击处理函数中第一个参数的名称。该名称覆盖了链接函数中的 $scope
参数。
//BAD
link: function($scope, $element, attrs) {
$element.bind('click', function($scope) {
alert($scope.msg);
})}
像这样修正你的代码:
//GOOD
link: function(scope, element, attrs) {
element.on('click', function clickHandler(event) {
console.log(scope.msg);
});
}
AngularJS jqLite invokes the click handler with a JQuery Event Object as the first argument not $scope
.
Is this the correct way to handle events on directives?
Why doesn't the ng-click
event ever work to call the function I have in my directive's controller?
ng-click
指令绑定到父作用域中的函数。
要将点击事件绑定到指令范围内的函数,请使用 element.on()
. It's how ng-click
gets the event from the browser. Look at the source code。
看你想得到什么
例如,如果您想在点击时绑定指令的功能,则不需要 link 功能。您可以简单地使用 ng-click 绑定外部 div 上的点击。看这个例子:http://jsbin.com/sanova/edit?html,js,output
但是如果你想在你的父控制器上调用一个函数,你需要在你的指令中使用 属性 传递对该函数的引用。看这个例子:http://jsbin.com/peqasu/edit?html,js,output
如您所见,我在两个示例中都在指令模板的外部 div 上放置了一个 ng-click 指令。单击指令控制器上的检查功能将被调用。在第一个示例中,简单地提醒消息,在第二个示例中,调用作为指令的 属性 传递的 greetFunction。
首先你需要知道智能组件和哑组件(指令)之间的区别。
在这里您可以阅读一篇很好的文章,解释智能组件和笨组件的区别,作者是 Redux: https://medium.com/@dan_abramov/smart-and-dumb-components-7ca2f9a7c7d0
的丹·阿布拉莫夫 (Dan Abramov)
当您了解这种差异后,您可以尝试编写更多愚蠢的组件和不太聪明的组件。这意味着您需要将所有逻辑保留在您的父组件上并将其传递给您的哑组件。
在前面的示例中,我们只在第二个示例中这样做。事实上,在那个例子中,我们将逻辑(我们的检查函数)保留在我们的父组件中,并且只传递对它的引用。通过这种方式,activity-header 组件不知道单击完成后要做什么。它只知道它必须调用一个函数,这个函数做什么不是它的问题。
在复杂的应用程序中这是一个很好的方法,因此您只需更改引用函数即可以不同的方式重用您的组件。
我已经有一段时间没有接触 angular js 了,当我写的时候,我们使用了一种带有 typescript 的风格,这对我来说非常简单。现在想写vanilla angular js 感觉有点乱
问题:
我有一个在其隔离范围内有几个变量的指令,我基本上想绑定到这个在每个 <ul>
内部产生的指令到一个点击事件。我尝试在 ng-click 上直接绑定一个函数,并使用 link 元素 e.t.c。单击绑定,但似乎我做错了什么,因为第一种方式没有任何反应,第二种方式未定义双向绑定变量。
这里是: https://plnkr.co/edit/OOBMs8pYONLjUE9lQXla?p=preview
activity-header.html
<div>
<h4>
Activity Name: {{activity.activity_name}}
</h4>
<h6>
Activity Start Date: {{activity.activity_start_date}}
</h6>
<h6>
Activity End Date: {{activity.activity_end_date}}
</h6>
<h6>
Participants: {{activity.participants}}
</h6>
</div>
activity-header.js
var app = angular.module('mainApp');
/*
app.controller('activityHeaderCtrl', ['$scope', function($scope) {
$scope.activity='';
$scope.msg='';
$scope.check = function() {
alert($scope.msg);
};
}]);
*/
app.directive('activityHeader', function() {
return {
restrict: 'AE',
templateUrl: 'activity-header.html',
controller: ['$scope', Controller],
scope: {
activity:'=',
msg:'='
},
link: function($scope, $element, attrs) {
$element.bind('click', function($scope) {
alert($scope.msg);
})}
};
function Controller($scope) {
$scope.check = function() {
alert($scope.msg);
};
}
});
index.html
<html ng-app="mainApp">
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.3.14/angular.min.js"></script>
<script src="script-main.js"></script>
<script src="activity-header.js"></script>
<body>
<div ng-controller="ctrl">
<h1>
Major Bla bla System
</h1>
<ul>
<li ng-repeat="x in events">
<div activity-header activity="x" msg="greetingsfriend" ng-click="check()"></div>
</li>
</ul>
<h6>
Beta v.0.2
</h6>
</div>
</body>
</html>
脚本-main.js
var app = angular.module('mainApp', []);
app.controller('ctrl', function ($scope) {
//$scope.events = ["Elections", "Protest", "Martial Law", "X-mas Celebration"];
$scope.events = [
{"activity_name": "Elections", "activity_start_date": "31/12/2014", "activity_end_date": "31/12/2015", "participants": "1453"},
{"activity_name": "Martial Law", "activity_start_date": "31/12/2014", "activity_end_date": "31/12/2015", "participants": "1821"},
{"activity_name": "Protest", "activity_start_date": "31/12/2014", "activity_end_date": "31/12/2015", "participants": "1940"},
{"activity_name": "X-mas Celebration", "activity_start_date": "31/12/2014", "activity_end_date": "31/12/2015", "participants": "2009"}
];
$scope.salute = function () {
alert('hello there');
};
});
(顺便说一句,我使用的是 Mozilla Firefox,否则我必须将其托管在 node.js 上以实现同源策略,不知道如何在 chrome/ Internet Explorer).
Any idea on how to handle the click?
您的问题是您使用 $scope
作为点击处理函数中第一个参数的名称。该名称覆盖了链接函数中的 $scope
参数。
//BAD
link: function($scope, $element, attrs) {
$element.bind('click', function($scope) {
alert($scope.msg);
})}
像这样修正你的代码:
//GOOD
link: function(scope, element, attrs) {
element.on('click', function clickHandler(event) {
console.log(scope.msg);
});
}
AngularJS jqLite invokes the click handler with a JQuery Event Object as the first argument not $scope
.
Is this the correct way to handle events on directives?
Why doesn't theng-click
event ever work to call the function I have in my directive's controller?
ng-click
指令绑定到父作用域中的函数。
要将点击事件绑定到指令范围内的函数,请使用 element.on()
. It's how ng-click
gets the event from the browser. Look at the source code。
看你想得到什么
例如,如果您想在点击时绑定指令的功能,则不需要 link 功能。您可以简单地使用 ng-click 绑定外部 div 上的点击。看这个例子:http://jsbin.com/sanova/edit?html,js,output
但是如果你想在你的父控制器上调用一个函数,你需要在你的指令中使用 属性 传递对该函数的引用。看这个例子:http://jsbin.com/peqasu/edit?html,js,output
如您所见,我在两个示例中都在指令模板的外部 div 上放置了一个 ng-click 指令。单击指令控制器上的检查功能将被调用。在第一个示例中,简单地提醒消息,在第二个示例中,调用作为指令的 属性 传递的 greetFunction。
首先你需要知道智能组件和哑组件(指令)之间的区别。
在这里您可以阅读一篇很好的文章,解释智能组件和笨组件的区别,作者是 Redux: https://medium.com/@dan_abramov/smart-and-dumb-components-7ca2f9a7c7d0
的丹·阿布拉莫夫 (Dan Abramov)当您了解这种差异后,您可以尝试编写更多愚蠢的组件和不太聪明的组件。这意味着您需要将所有逻辑保留在您的父组件上并将其传递给您的哑组件。
在前面的示例中,我们只在第二个示例中这样做。事实上,在那个例子中,我们将逻辑(我们的检查函数)保留在我们的父组件中,并且只传递对它的引用。通过这种方式,activity-header 组件不知道单击完成后要做什么。它只知道它必须调用一个函数,这个函数做什么不是它的问题。
在复杂的应用程序中这是一个很好的方法,因此您只需更改引用函数即可以不同的方式重用您的组件。