Angularjs 控制器函数 vs 指令函数
Angularjs controller function vs directive function
最近我一直在构建一些模块,其中一些我只使用控制器(控制器设置在我已经需要用来加载模板的现有指令中)来实现服务和视图之间的这种通信,因为示例:
$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
等等。还要考虑性能。
这些调用方式有什么区别?用作调用函数的最佳选择是什么?
重申一下,您正在对单击事件调用服务方法,并且想知道放置该逻辑的最佳位置。
让我们看看您的每个示例:
控制器
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 指令的完美方法。
带Link函数的指令
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
这样做是六个,另一个是六个。
最近我一直在构建一些模块,其中一些我只使用控制器(控制器设置在我已经需要用来加载模板的现有指令中)来实现服务和视图之间的这种通信,因为示例:
$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
等等。还要考虑性能。
这些调用方式有什么区别?用作调用函数的最佳选择是什么?
重申一下,您正在对单击事件调用服务方法,并且想知道放置该逻辑的最佳位置。
让我们看看您的每个示例:
控制器
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 指令的完美方法。
带Link函数的指令
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
这样做是六个,另一个是六个。