使用控制器作为语法仅更新其中一个范围
Using controller as syntax only updates one of the scopes
我对 controller as
语法有点困惑,因为我以前从未使用过它。我想知道解决这个问题的正确方法。一直没能搜索到类似的问题。
我有一个菜单和一个切换菜单的按钮。菜单有自己的作用域,按钮有另一个作用域,因为它们位于两个独立的文件和容器中。
当我单击按钮时,它只会更新按钮范围内的 nav.isActive
。我创建了一个用于存储状态的服务,当我想到它时我不应该这样做......应该吗?因为观察该值是否发生变化的唯一方法是使用观察者,这需要我使用 $scope
因为 this
没有 $watch
函数,但是,我想尽可能避免这种情况,因为它会影响性能,这在这个项目中很重要。
使用 controller as
语法时,从另一个 "scope" 更新一个 "scope" 变量的正确方法是什么?
控制器:
nav.controller('NavCtrl', ['navState', function(navState) {
var nav = this;
nav.menu = [
{icon: 'color_lens', href: ''},
{icon: 'color_lens', href: 'about'},
{icon: 'color_lens', href: 'contact'},
{icon: 'color_lens', href: 'logout'},
{icon: 'color_lens', href: 'faq'}
];
nav.toggleMenu = function() {
nav.isActive = navState.checkState();
}
}]);
将值从一个作用域传递到另一个作用域的服务:
nav.service('navState', [function() {
var isActive = false;
this.checkState = function() {
isActive = !isActive;
return !isActive;
}
}]);
菜单标记(menu.html):
<nav class="si-wrapper si-dark" ng-controller="NavCtrl as nav" ng-class="{active: nav.isActive}">
<ul class="si-list">
<li class="si-item" ng-repeat="item in nav.menu">
<a href="#/{{item.href}}">
<div class="si-inner-item">
<i class="material-icons md-36" ng-bind="item.icon"></i>
</div>
</a>
</li>
</ul>
<h1>{{nav.isActive}}</h1> <!-- This doesn't change -->
</nav>
切换菜单的按钮(header.html):
<div ng-controller="NavCtrl as nav">
<button ng-click="nav.toggleMenu()">Toggle</button>
<span>{{nav.isActive}}</span> <!-- This updates however -->
</div>
您的问题是没有为其中一个控制器设置 nav.isActive
。基本上每当你使用 ng-controller
时,都会创建一个新的控制器(和 $scope
)。因此,对于您的每个控制器,需要为相关视图设置 $scope.isActive
以引用它。
在您发布的代码中,isActive
仅在 toggleMenu()
为 运行 时设置,这仅在 header.html.
中发生
为了让您的代码正常工作,只需在控制器负载上设置 isActive
。例如:
nav.controller('NavCtrl', ['navState', function(navState) {
// put isActive on the scope on controller load
this.activeState = navState.getState();
nav.toggleMenu = function() {
navState.toggleState();
};
}]);
您需要通过分离状态访问和状态操作来改善您的服务。还将它包装在容器对象中将确保您不会有任何范围层次结构问题。
nav.service('navState', [function() {
var state = {
isActive: false
};
this.toggleState = function() {
state.isActive = !state.isActive;
};
this.getState = function(){
return state;
};
}]);
然后你需要在视图中使用 `activeState.isActive'。
现在您将拥有一个具有可共享状态的服务,以及两个在加载时都引用相同服务的控制器。然后在您的菜单视图中,当您切换状态时,两个控制器范围都会更新。
来自 angularjs 文档:
When a Controller is attached to the DOM via the ng-controller directive, Angular will instantiate a new Controller object, using the specified Controller's constructor function. A new child scope will be created and made available as an injectable parameter to the Controller's constructor function as $scope.
此外,ng-controller 指令有一个从其父范围继承的范围。因此,您还可以在父级中定义共享数据。它可以在 'NavCtrl' 范围内访问。但是,由于您想将控制器用作 synax,一种方法是在服务的帮助下共享数据。
但是,我不喜欢使用 'ng-controller' 指令的方法。另一种解决方案是将其替换为指令层次结构,其中子指令将需要父指令。也在那里使用 'controllerAs' 属性。
我对 controller as
语法有点困惑,因为我以前从未使用过它。我想知道解决这个问题的正确方法。一直没能搜索到类似的问题。
我有一个菜单和一个切换菜单的按钮。菜单有自己的作用域,按钮有另一个作用域,因为它们位于两个独立的文件和容器中。
当我单击按钮时,它只会更新按钮范围内的 nav.isActive
。我创建了一个用于存储状态的服务,当我想到它时我不应该这样做......应该吗?因为观察该值是否发生变化的唯一方法是使用观察者,这需要我使用 $scope
因为 this
没有 $watch
函数,但是,我想尽可能避免这种情况,因为它会影响性能,这在这个项目中很重要。
使用 controller as
语法时,从另一个 "scope" 更新一个 "scope" 变量的正确方法是什么?
控制器:
nav.controller('NavCtrl', ['navState', function(navState) {
var nav = this;
nav.menu = [
{icon: 'color_lens', href: ''},
{icon: 'color_lens', href: 'about'},
{icon: 'color_lens', href: 'contact'},
{icon: 'color_lens', href: 'logout'},
{icon: 'color_lens', href: 'faq'}
];
nav.toggleMenu = function() {
nav.isActive = navState.checkState();
}
}]);
将值从一个作用域传递到另一个作用域的服务:
nav.service('navState', [function() {
var isActive = false;
this.checkState = function() {
isActive = !isActive;
return !isActive;
}
}]);
菜单标记(menu.html):
<nav class="si-wrapper si-dark" ng-controller="NavCtrl as nav" ng-class="{active: nav.isActive}">
<ul class="si-list">
<li class="si-item" ng-repeat="item in nav.menu">
<a href="#/{{item.href}}">
<div class="si-inner-item">
<i class="material-icons md-36" ng-bind="item.icon"></i>
</div>
</a>
</li>
</ul>
<h1>{{nav.isActive}}</h1> <!-- This doesn't change -->
</nav>
切换菜单的按钮(header.html):
<div ng-controller="NavCtrl as nav">
<button ng-click="nav.toggleMenu()">Toggle</button>
<span>{{nav.isActive}}</span> <!-- This updates however -->
</div>
您的问题是没有为其中一个控制器设置 nav.isActive
。基本上每当你使用 ng-controller
时,都会创建一个新的控制器(和 $scope
)。因此,对于您的每个控制器,需要为相关视图设置 $scope.isActive
以引用它。
在您发布的代码中,isActive
仅在 toggleMenu()
为 运行 时设置,这仅在 header.html.
为了让您的代码正常工作,只需在控制器负载上设置 isActive
。例如:
nav.controller('NavCtrl', ['navState', function(navState) {
// put isActive on the scope on controller load
this.activeState = navState.getState();
nav.toggleMenu = function() {
navState.toggleState();
};
}]);
您需要通过分离状态访问和状态操作来改善您的服务。还将它包装在容器对象中将确保您不会有任何范围层次结构问题。
nav.service('navState', [function() {
var state = {
isActive: false
};
this.toggleState = function() {
state.isActive = !state.isActive;
};
this.getState = function(){
return state;
};
}]);
然后你需要在视图中使用 `activeState.isActive'。
现在您将拥有一个具有可共享状态的服务,以及两个在加载时都引用相同服务的控制器。然后在您的菜单视图中,当您切换状态时,两个控制器范围都会更新。
来自 angularjs 文档:
When a Controller is attached to the DOM via the ng-controller directive, Angular will instantiate a new Controller object, using the specified Controller's constructor function. A new child scope will be created and made available as an injectable parameter to the Controller's constructor function as $scope.
此外,ng-controller 指令有一个从其父范围继承的范围。因此,您还可以在父级中定义共享数据。它可以在 'NavCtrl' 范围内访问。但是,由于您想将控制器用作 synax,一种方法是在服务的帮助下共享数据。
但是,我不喜欢使用 'ng-controller' 指令的方法。另一种解决方案是将其替换为指令层次结构,其中子指令将需要父指令。也在那里使用 'controllerAs' 属性。