$ emit vs callback в родительском директиве по связям с сообществом лучший подход
Я пытаюсь понять, что является наилучшим подходом GENERIC для связи между родительской и дочерней директивой с изолированными областями (они могут быть элементами многократного использования).
означает, что дочерняя директива должна каким-либо образом обновлять родительскую директиву (оба имеют изолированные области),
нужно ли мне
передать функцию обратного вызова:
например:
.directive('filterReviewStepBox', function () {
return {
restrict: 'EA',
scop: {
//some data
},
template: '<div>text<reusable-dir></reusable-dir call-back="foo"></div>',
link: function (scope, elem, attrs) {
scope.foo = function () {
console.log('bar');
};
}
};
}).directive('reusableDir', function () {
return {
restrict: 'EA',
scope: {
callBack: '=callBack'
//other data
},
template: '<div>text<button type="button" ng-click="bar"></button></div>',
link: function (scope, elem, attrs) {
scope.bar = function () {
scope.callBack();
}
}
};
});
или я должен использовать $emit():
например:
directive('filterReviewStepBox', function () {
return {
restrict: 'EA',
scope: {
// some data
},
template: '<div>text<reusable-dir></reusable-dir></div>',
link: function (scope, elem, attrs) {
scope.$on('foo', function () {
console.log('bar');
});
}
};
}).directive('reusableDir', function () {
return {
restrict: 'EA',
scope: { //some data
},
template: '<div>text<button type="button" ng-click="bar"></button></div>',
link: function (scope, elem, attrs) {
scope.bar = function () {
scope.$emit('foo');
};
}
};
});
Я чувствую, что излучать легче понять в более широких масштабах, но беспокоит производительность и накладные расходы, но Im все еще не уверен
попробовал найти лучший подход в Интернете, но Im все еще топал
ИЗМЕНИТЬ
Я забыл о
требуется
вариант.
но я все еще не уверен, что это самое правильное решение.
Поскольку это не позволяет мне повторно использовать ребенка или внука, и это делает директиву единым целым.
Ответы
Ответ 1
Лично я стараюсь избегать генерации собственных пользовательских событий. Главным образом потому, что невероятно легко вызывать нежелательное распространение событий или пузырение (часто вызывающее нежелательные перехваты), но и из-за систематического "шума", который в больших приложениях может стать очень трудным для управления.
Мои личные взгляды в стороне, хотя, и если это более "перспективный" подход, который вы ищете, подход обратного вызова, безусловно, самый безопасный. Вот почему...
- Angular2 рекомендует разработчикам раскрывать атрибуты
onChange
из директив и компонентов, которые зависят от связи между родителями и родителями. Обратите внимание, что это не что иное, как связанные функции, и должны быть соответствующим образом определены в привязках или областях данного компонента или директивы.
- Как и в предыдущем случае, Angular2 документирует метод
ngOnChanges
, который может быть определен любым контроллером, желающим подписаться на изменения привязок. Если этот параметр предоставляется, этот метод вызывается до того, как произойдет какая-либо манипуляция с DOM (с новыми значениями границ), поэтому он станет идеальным кандидатом на более "общую" родительскую связь с дочерним по сравнению с текущей версией AngularJS $scope.$watch
.
Что-то, о чем не упоминалось, заключается в том, что связь через службы по-прежнему рекомендуется как в AngularJS, так и в Angular2.
Ответ 2
Для этой цели лучше всего использовать атрибут "require".
Полное руководство по директивам сообщает нам об атрибуте require: https://docs.angularjs.org/api/ng/service/ $compile
Требовать другую директиву и вводить ее контроллер в качестве четвертого аргумент функции связывания. Требование принимает имя строки (или массив строк) директивы (ов), которая должна пройти.
Требовать, просто указывая директиве, он должен искать какую-либо родительскую директиву и принимать ее контроллер. Вы можете указать директиву для поиска в родительских элементах с префиксом ^ и указать, является ли это требование необязательным? префикс.
Я изменил ваш пример, поэтому reusableDir может вызывать filterReviewStepBox-контроллер, но может также использоваться один.
http://jsbin.com/gedaximeko/edit?html,js,console,output
angular.module('stackApp', [])
.directive('filterReviewStepBox', function () {
return {
restrict: 'EA',
scope: {
// some data
},
template: '<div>text<reusable-dir></reusable-dir></div>',
link: function (scope, elem, attrs) {
},
controller : function() {
this.notify = function(value) {
console.log('Notified : ' + value);
};
},
controllerAs: 'vm',
bindToController: true
};
}).directive('reusableDir', function () {
return {
restrict: 'EA',
scope: { //some data
},
require: '?^filterReviewStepBox',
template: '<div>text<button type="button" ng-click="bar()"></button></div>',
link: function (scope, elem, attrs, controller) {
scope.bar = function () {
if (controller) {
controller.notify('foo');
}
};
}
};
});
Ответ 3
Я думаю, что речь идет не только о производительности, вам также необходимо учитывать несколько факторов с точки зрения дизайна и обслуживания.
-
Метод обратного вызова. Это, пожалуй, самый эффективный вариант. Директива child просто вызовет один метод родительской директивы, no
накладные расходы. Здесь объясняется несколько вариантов:
fooobar.com/info/85274/...
-
Эмит (или, в этом отношении, широковещательный). Этот метод публикует событие для всех $scope (s) up (emit) или down (broadcast) для иерархии,
относительно дорогостоящий, но он дает вам возможность смотреть и обрабатывать
событие, где доступно $scope.
-
Инъекционная общая служба. Эта опция может использоваться, если вы хотите вызвать какой-либо метод, где $scope недоступен. Тем не менее, она создавала жесткую зависимость от обслуживания. Это больше
pub-sub.