我有一个控制器,应该从输入字段写入文本到屏幕。如果我单独使用这个控制器,一切都按预期工作:
(function() {
angular.module('test', []);
function OneCtrl() {
vm = this;
vm.changeHandler = changeHandler;
vm.item = "";
vm.value = "";
}
angular
.module('test')
.controller('OneCtrl', OneCtrl);
var changeHandler = function() {
vm.value = vm.item;
console.log(vm.item);
};
})();
试试:http://codepen.io/minuskruste/pen/qdrZqq
然而,如果我添加另一个具有相同行为的控制器,就会发生一些非常奇怪的事情。首先,字段1的输入不再发送到控制台,文本也不会插入到html正文中。其次,当我在输入字段2中输入一些东西时,它的行为是正确的。如果我现在回到字段1并在那里输入,突然字段2输入输出到控制台,即使控制器2从未被告知这样做!这是控制器2:
(function(){
function TwoController(){
vm = this;
vm.changeHandler = changeHandler;
vm.item = "";
vm.value = "";
}
angular
.module('test')
.controller('TwoController', TwoController);
var changeHandler = function() {
vm.value = vm.item;
};
}) ();
试试:http://codepen.io/minuskruste/pen/QbpNdY
这是正常行为吗?我对此感到非常惊讶。我还检查了changeHandler()
是否泄露到全局空间,但由于我把所有东西都放在闭包中,情况并非如此。此外,这在不同的平台上是一致的,例如Chrome和FF。什么好主意吗?
您遇到的部分问题是您在没有var
关键字的情况下声明vm
,这使其成为全局变量。
但是,var
关键字的vm
在控制器的本地作用域中。因此,它不再适用于changeHandler()
。如果您重新排序代码并在控制器中声明changeHandler()
,它将工作。
(function() {
angular.module('test', []);
function OneCtrl() {
var vm = this;
vm.item = "";
vm.value = "";
vm.changeHandler = function() {
vm.value = vm.item;
console.log(vm.item);
}
}
angular
.module('test')
.controller('OneCtrl', OneCtrl);
})();
(function(){
function TwoController() {
var vm = this;
vm.item = "";
vm.value = "";
vm.changeHandler = function() {
vm.value = vm.item;
console.log(vm.item);
}
}
angular
.module('test')
.controller('TwoController', TwoController);
})();
<script src="//cdnjs.cloudflare.com/ajax/libs/angular.js/1.3.14/angular.min.js"></script>
<body ng-app="test">
<h1>Choice array</h1>
<div>
<form novalidate ng-controller="OneCtrl as one">
<input type="text" ng-change="one.changeHandler()" ng-model="one.item">
<div>{{one.value}}</div>
</form>
<br><br><br>
</div>
<div>
<form novalidate ng-controller="TwoController as two">
<input type="text" ng-change="two.changeHandler()" ng-model="two.item">
<div>{{two.value}}</div>
</form>
</div>
</body>
这是因为您正在使用全局"vm"变量,它包含这个控制器的引用。对于第二个控制器,您将使用第二个控制器的参考覆盖vm变量。
我已经更新了你的代码来使用正确的this引用
angular还支持另一种数据绑定方法,使用特殊的$scope对象:https://docs.angularjs.org/guide/scope
(function() {
angular.module('test', []);
function OneCtrl($scope) {
// This construction makes sure I know which context is addressed. I can now hand vm (view-model) inside an object and the context doesn't change.
this.changeHandler = angular.bind(this, changeHandler);
this.item = "";
this.value = "";
}
angular
.module('test')
.controller('OneCtrl', OneCtrl);
var changeHandler = function() {
this.value = this.item;
console.log(this.item);
};
})();
(function(){
function TwoController(){
// This construction makes sure I know which context is addressed. I can now hand vm (view-model) inside an object and the context doesn't change.
this.changeHandler = angular.bind(this, changeHandler);
this.item = "";
this.value = "";
}
angular
.module('test')
.controller('TwoController', TwoController);
var changeHandler = function() {
this.value = this.item;
};
})();
<script src="//cdnjs.cloudflare.com/ajax/libs/angular.js/1.3.14/angular.min.js"></script>
<body ng-app="test">
<h1>Choice array</h1>
<div>
<form novalidate ng-controller="OneCtrl as one">
<input
type="text"
ng-change="one.changeHandler()" ng-model="one.item">
<div>{{one.value}}</div>
</form>
<br>
<br>
<br>
</div>
<div>
<form novalidate ng-controller="TwoController as two">
<input
type="text"
ng-change="two.changeHandler()" ng-model="two.item">
<div>{{two.value}}</div>
</form>
</div>
</body>
这是一篇关于Controller As语法的好文章。
http://www.johnpapa.net/angularjss-controller-as-and-the-vm-variable/如果你在每个控制器中声明vm变量,它将防止你看到的覆盖行为。Javascript是函数作用域的,这意味着如果它在当前函数中没有找到vm的变量声明,它将沿着原型链向上查找,直到找到声明(var vm)。如果它在全局作用域中没有找到任何声明,它将自动为您创建一个。通过在每个控制器内部声明,你可以防止它们共享相同的全局作用域。
function OneCtrl() {
// This construction makes sure I know which context is addressed. I can now hand vm (view-model) inside an object and the context doesn't change.
var vm = this;
vm.item = "";
vm.value = "";
vm.changeHandler = function() {
console.log(vm.item);
vm.value = vm.item;
};
}
http://plnkr.co/edit/KdZvG7d2COLNcjRIfyHb?p =预览