Angular 摘要周期 运行 但 ng-bind 值未更新
Angular Digest cycle being ran but ng-bind value not updating
我有一个包含导航栏的父视图,在该视图内部我有一个 <div ui-view>
元素,它呈现我所在的任何子视图。
我想根据子视图的路线有条件地 show/hide 父视图中的导航栏。现在,我有这个:
<nav ng-show="!vm.hideNavbar">
第一次加载我的应用程序时,vm.hideNavbar
设置为 true,这按预期工作。
vm.hideNavbar
改为false后,绑定值不更新。还是true
.
我应用中的每个控制器都扩展了这个 BaseController
:
export class BaseController {
public hideNavbar: boolean;
constructor(public $scope: IBaseScope, private $state: ng.ui.IStateService) {
if ($state.current.url === '/login') {
this.hideNavbar = true;
} else {
this.hideNavbar = false;
}
$scope.vm = this;
}
}
因此,每次加载新控制器时,它都会调用 BaseController
的构造函数并有条件地设置 $scope.vm.hideNavbar
。如果我在这个构造函数的末尾立即 运行 $scope.$apply()
,angular 会抛出错误,说明摘要周期已经在 运行.
因此,摘要周期正在 运行,但我认为的值没有更新。我唯一的想法是,自从我的初始控制器和我导航到的控制器都扩展了这个控制器以来,我已经实例化了 BaseController
的多个副本。所以,现在,我的绑定值vm.hideNavbar
还在看老控制器
我的方向正确吗?我该如何解决这个问题?
在这种情况下,我建议使用 view inheritance
(不是 controller
,不是 state
) 。在此处查看更多详细信息:
- How do I share $scope data between states in angularjs ui-router?
- How to inherit resolve data in ui-router
有a working example
我们需要的是 'root'
状态。它将是任何其他 state
(states family) 的 super parent。这可能是状态定义:
$stateProvider
.state('root', {
abstract: true,
templateUrl: 'layout.tpl.html',
controller: MyNamespace.RootCtrl,
})
.state('login', {
parent: "root",
url: "/login",
templateUrl: 'tpl.html',
controller: MyNamespace.LoginCtrl,
})
.state('home', {
parent: "root",
url: "/home",
templateUrl: 'tpl.html',
controller: MyNamespace.HomeCtrl,
})
甚至其他一些州等级制度也将从 'root'
州开始:
$stateProvider
.state('parent', {
parent: "root",
url: "/parent",
templateUrl: 'tpl.html',
controller: MyNamespace.ParentCtrl
})
.state('parent.child1', {
url: "/child1",
templateUrl: 'tpl.html',
controller: MyNamespace.Child1Ctrl
})
.state('parent.child2', {
url: "/child2",
templateUrl: 'tpl.html',
controller: MyNamespace.Child2Ctrl
})
我们可以看到很多controllers:...
被定义,这里是:
module MyNamespace {
// the real SUPER parent of all states
// but it is about VIEW inheritance (its $scope)
// not about controller hierarchy
export class RootCtrl extends BaseController {
}
export class HomeCtrl extends BaseController {
}
export class LoginCtrl extends BaseController {
}
export class ParentCtrl extends BaseController {
}
export class Child1Ctrl extends BaseController {
}
export class Child2Ctrl extends BaseController {
}
}
如片段评论中所述 - 存在继承,但仅在代码级别。传递的 $scope
由视图层次结构继承。
视图层次结构中的第一个控制器是 RootCtrl
,它实际上是唯一一个分配(创建)共享参考模型的控制器 rootSetting : {}
它们都源自这个控制器基础:
module MyNamespace {
export interface IRootSetting {
hideNavbar: boolean;
}
export interface IMyRootScope extends ng.IScope {
rootSetting: IRootSetting
}
export interface IBaseScope extends IMyRootScope {
}
export class BaseController {
public hideNavbar: boolean;
static $inject = ['$scope', '$state'];
constructor(public $scope: IBaseScope,
protected $state: ng.ui.IStateService) {
// will be in fact assigned in the RootCtrl only
// all others (children) will get that reference
// via scope inheritance
$scope.rootSetting = $scope.rootSetting || {hideNavbar: false};
if ($state.current.url === '/login') {
this.$scope.rootSetting.hideNavbar = true;
} else {
this.$scope.rootSetting.hideNavbar = false;
}
}
}
}
有了这个根模板:
<div>
<div ng-if="!rootSetting.hideNavbar">
... // navbar
</div>
<div ui-view="">
// standard content of child views
</div>
</div>
我们可以看到,这里我们评估共享参考模型rootSetting
及其属性hideNavbar
这就是view inheritance
与UI-Router
的真正优势。
实际查看 here
我有一个包含导航栏的父视图,在该视图内部我有一个 <div ui-view>
元素,它呈现我所在的任何子视图。
我想根据子视图的路线有条件地 show/hide 父视图中的导航栏。现在,我有这个:
<nav ng-show="!vm.hideNavbar">
第一次加载我的应用程序时,vm.hideNavbar
设置为 true,这按预期工作。
vm.hideNavbar
改为false后,绑定值不更新。还是true
.
我应用中的每个控制器都扩展了这个 BaseController
:
export class BaseController {
public hideNavbar: boolean;
constructor(public $scope: IBaseScope, private $state: ng.ui.IStateService) {
if ($state.current.url === '/login') {
this.hideNavbar = true;
} else {
this.hideNavbar = false;
}
$scope.vm = this;
}
}
因此,每次加载新控制器时,它都会调用 BaseController
的构造函数并有条件地设置 $scope.vm.hideNavbar
。如果我在这个构造函数的末尾立即 运行 $scope.$apply()
,angular 会抛出错误,说明摘要周期已经在 运行.
因此,摘要周期正在 运行,但我认为的值没有更新。我唯一的想法是,自从我的初始控制器和我导航到的控制器都扩展了这个控制器以来,我已经实例化了 BaseController
的多个副本。所以,现在,我的绑定值vm.hideNavbar
还在看老控制器
我的方向正确吗?我该如何解决这个问题?
在这种情况下,我建议使用 view inheritance
(不是 controller
,不是 state
) 。在此处查看更多详细信息:
- How do I share $scope data between states in angularjs ui-router?
- How to inherit resolve data in ui-router
有a working example
我们需要的是 'root'
状态。它将是任何其他 state
(states family) 的 super parent。这可能是状态定义:
$stateProvider
.state('root', {
abstract: true,
templateUrl: 'layout.tpl.html',
controller: MyNamespace.RootCtrl,
})
.state('login', {
parent: "root",
url: "/login",
templateUrl: 'tpl.html',
controller: MyNamespace.LoginCtrl,
})
.state('home', {
parent: "root",
url: "/home",
templateUrl: 'tpl.html',
controller: MyNamespace.HomeCtrl,
})
甚至其他一些州等级制度也将从 'root'
州开始:
$stateProvider
.state('parent', {
parent: "root",
url: "/parent",
templateUrl: 'tpl.html',
controller: MyNamespace.ParentCtrl
})
.state('parent.child1', {
url: "/child1",
templateUrl: 'tpl.html',
controller: MyNamespace.Child1Ctrl
})
.state('parent.child2', {
url: "/child2",
templateUrl: 'tpl.html',
controller: MyNamespace.Child2Ctrl
})
我们可以看到很多controllers:...
被定义,这里是:
module MyNamespace {
// the real SUPER parent of all states
// but it is about VIEW inheritance (its $scope)
// not about controller hierarchy
export class RootCtrl extends BaseController {
}
export class HomeCtrl extends BaseController {
}
export class LoginCtrl extends BaseController {
}
export class ParentCtrl extends BaseController {
}
export class Child1Ctrl extends BaseController {
}
export class Child2Ctrl extends BaseController {
}
}
如片段评论中所述 - 存在继承,但仅在代码级别。传递的 $scope
由视图层次结构继承。
视图层次结构中的第一个控制器是 RootCtrl
,它实际上是唯一一个分配(创建)共享参考模型的控制器 rootSetting : {}
它们都源自这个控制器基础:
module MyNamespace {
export interface IRootSetting {
hideNavbar: boolean;
}
export interface IMyRootScope extends ng.IScope {
rootSetting: IRootSetting
}
export interface IBaseScope extends IMyRootScope {
}
export class BaseController {
public hideNavbar: boolean;
static $inject = ['$scope', '$state'];
constructor(public $scope: IBaseScope,
protected $state: ng.ui.IStateService) {
// will be in fact assigned in the RootCtrl only
// all others (children) will get that reference
// via scope inheritance
$scope.rootSetting = $scope.rootSetting || {hideNavbar: false};
if ($state.current.url === '/login') {
this.$scope.rootSetting.hideNavbar = true;
} else {
this.$scope.rootSetting.hideNavbar = false;
}
}
}
}
有了这个根模板:
<div>
<div ng-if="!rootSetting.hideNavbar">
... // navbar
</div>
<div ui-view="">
// standard content of child views
</div>
</div>
我们可以看到,这里我们评估共享参考模型rootSetting
及其属性hideNavbar
这就是view inheritance
与UI-Router
的真正优势。
实际查看 here