自从我开始学习AngularJS以来,我已经看到了从视图中调用控制器函数的不同方法。
假设我们在AngularJS中有一个Todo列表应用程序,您可以在其中添加和删除Todo列表项:
function TodoListCtrl() {
var vm = this;
vm.addItem = addItem;
vm.removeItem = removeItem;
activate();
function activate() {
vm.list = [];
}
function addItem() {
vm.list.push(vm.newItem);
// reset the form
vm.newItem = null;
}
function removeItem(item) {
vm.list.splice(vm.list.indexOf(item, 1));
}
}
我们的HTML:
<h3>Todo List</h3>
<ul>
<li ng-repeat="item in vm.list">
{{ item }} <a ng-click="vm.removeItem(item)">Remove</a>
</li>
</ul>
<h4>Add Item</h4>
<input type="text" ng-model="vm.newItem" /> <button ng-click="vm.addItem()">Add</button>
在此示例中,addItem
函数取决于要设置的vm.newItem
以添加新列表项。但是,它也可以重写为:
function addItem(item) {
vm.list.push(item);
// reset the form
vm.newItem = null;
}
我们的HTML更新如下:
<button ng-click="vm.addItem(vm.newItem)">Add</button>
我可以看到这使得函数更容易测试,因为我们不依赖于控制器的状态,但我们没有完全避免它,因为我们在添加项目后重置vm.newItem
。
当我们应该从视图中传递参数以及何时可以依赖控制器的内部状态时,是否有任何最佳实践?
答案 0 :(得分:2)
传递vm.newItem
表示您在视图中的2个位置拥有它。虽然可能很清楚,但它也在重复自己,让你可能会让一个人失去同步。还有什么额外价值?我认为很明显已经没有这样了。
<input type="text" ng-model="vm.newItem" />
<button ng-click="vm.addItem()">Add</button>
否则你有这个重复。
<input type="text" ng-model="vm.newItem" />
<button ng-click="vm.addItem(vm.newItem)">Add</button>
你说它更容易测试,但为什么?您正在测试控制器上的一个函数,因此期望该函数在同一个控制器上使用属性是完全正确的。您将依赖项模拟到控制器,但不是模块的成员。
答案 1 :(得分:1)
在您展示的两种情况下,函数addItem
都会对控制器的内部状态产生副作用(使用vm.newItem = null;
),因此无法单独进行测试。
然而,在第二种情况下,传递一个不同的变量甚至没有意义,因为它会使语句vm.newItem = null;
可能出错。
使功能完全无状态:
vm.addItem(item){
vm.list.push(item);
}
您需要从视图中重置表单:
<input type="text" ng-model="vm.newItem">
<button ng-click="vm.addItem(); vm.newItem = null">Add</button>
如果重置表单是仅查看问题,则可以可以接受。如果没有,那么这种方法完全不起作用,因为它可能使您的控制器处于错误状态(vm.newItem
仍然指向列表中新添加的项目)
在一天结束时,这取决于您的特定用例。如果你总是只有一个你可以“添加”的项目,那么传递一个显式参数最多是多余的。
但是,如果可以为视图中任何新创建的项调用addItem
,那么显式传递引用可能是唯一的方法。
测试方面,您应该始终测试控制器在操作后是否处于一致状态。