最近我一直在构建一些模块,其中一些模块我只使用控制器(控制器在我已经需要用来加载模板的现有指令中设置),以便在服务和视图之间进行通信,例如:
$scope.callFunction = function(data) {
factRequest = saveData(data);
};
我还注意到我可以在指令中执行此操作,如下所示:
link:function(scope) {
scope.callFunction = function(data) {
factRequest.saveData(data);
}
}
//or..
link:function(scope, element, attr) {
attrValue = attr.myValue;
element.bind('click', function(attrValue) {
factRequest.saveData(attrValue);
});
}
//or even..
link:function(scope, element, attr) {
attrValue = attr.myValue;
element.bind('click', function(attrValue) {
factRequest.saveData(attrValue);
});
var elButton = element.fin('span'); //for example
elButton.bind('click', function(attrValue) {
factRequest.saveData(attrValue);
});
}
考虑这种可重用对象的场景,例如,它在多个页面上显示并具有通用功能的产品,例如addFavorite
,addCart
,addWishList
等..还考虑了表现。
这些通话方法有什么区别?什么是用作呼叫功能的最佳选择?
答案 0 :(得分:2)
要重申,您正在调用点击事件的服务方法,并想知道放置该逻辑的最佳位置。
让我们看看你的每个例子:
angular.module('myApp').controller('MyController', function($scope, factRequest) {
$scope.callFunction = function(data) {
factRequest.saveData(data);
};
});
首先,每当我发现自己将$scope
注入控制器时,我就会质疑我的方法。这是因为如果您依赖于子控制器中的这些变量,则向当前作用域添加变量会创建隐藏的依赖项 - 如果不是,则不需要这样做。
相反,您应该使用controllerAs
语法并将该函数添加到控制器本身。像这样:
angular.module('myApp').controller('MyController', function(factRequest) {
var vm = this;
vm.callFunction = function(data) {
factRequest.saveData(data);
};
});
...您可以在模板中访问它:
<div ng-controller="MyController as vm">
<input ng-model="vm.data">
<button ng-click="vm.callFunction(vm.data)">
Click Me!
</button>
</div>
这是一种利用原生Angular指令的完美方法。
angular.module('myApp').directive('myDirective', function(factRequest) {
return {
link: function(scope) {
scope.callFunction = function(data) {
factRequest.saveData(data);
}
}
};
});
同样,我不喜欢这样,因为您要将功能添加到范围。如果您有一个指令并希望向模板公开某些功能,则应使用控制器。例如:
angular.module('myApp').directive('myDirective', function() {
return {
controller: 'MyDirectiveController',
controllerAs: 'myDir',
template: '<input ng-model="myDir.data">' +
'<button ng-click="myDir.callFunction(myDir.data)">' +
'Click Me!' +
'</button>'
};
}).controller('MyDirectiveController', function(factRequest) {
var myDir = this;
myDir.callFunction = function(data) {
factRequest.saveData(data);
}
});
这与第一个示例基本相同,只是它现在是一个可重用的组件。
angular.module('myApp').directive('myDirective', function(factRequest) {
return {
link: function(scope, element, attr) {
element.on('click', function() {
factRequest.saveData(scope.$eval(attr.myValue));
});
}
};
});
注意我在这里采取了一些自由。首先,事件处理函数将事件对象作为其第一个参数,因此尝试传递attr.myValue
将不起作用。另外,我调用了scope.$eval()
,这是一种支持在myValue
属性中使用Angular表达式的最佳做法。
我最喜欢这种方法,因为它并不依赖于ng-click
等其他指令的使用。换句话说,这个指令更加独立。
我应该补充的一点是,当从DOM中删除元素时,Angular不会删除此事件侦听器。在指令之后进行清理是最佳做法,如下所示:
angular.module('myApp').directive('myDirective', function(factRequest) {
return {
link: function(scope, element, attr) {
function onClick() {
factRequest.saveData(scope.$eval(attr.myValue));
}
element.on('click', onClick);
scope.$on('$destroy', function() {
element.off('click', onClick);
});
}
};
});
从绩效角度来看,所有这些方法大致相同。前两个人不会自己添加任何观察者,但是ng-click
和ng-model
这样做的是六个,另一个是六个。