我正在构建一个Web应用程序,我有一个屏幕,它包含五个部分,每个部分代表一个级别,区域是我的树的更高级别,当我点击该区域的任何卡片时,系统应该返回该区域的技能等。
我需要根据用户访问的内容更改网址和状态,例如,如果用户访问某项技能,则网址必须为
example.com/#/curriculum/skill/<skillId>
如果我访问此链接,它应该自动加载此技能及其父级的功能,在这种情况下是区域。
我有一个控制器用于区域,技能,能力,知识和标准,在每个控制器中我都有一个动作来加载树的下一级,看起来像那样
$scope.loadSkills = function (id) {
Area.loadSkills(...)
$state.go('curriculo.skill', {id: this.current.id}, {nofity: false, reload: false});
}
这些是我的州
$stateProvider
.state('curriculum', {
url: '/curriculum',
templateUrl: '/templates/curriculo.html',
})
.state('curriculum.are', {
url: '/area/:id',
template: '',
})
.state('curriculum.skill', {
url: '/skill/:id',
template: '',
})
.state('curriculum.capability', {
url: '/capability/:id',
})
.state('curriculum.knowledge', {
url: '/knowledge/:id',
})
.state('curriculum.criteria', {
url: '/criteria/:id',
});
我是Angular的新手,我不知道该怎么做,我应该在这种情况下创建多个嵌套视图,如果是这样,我如何根据网址加载我需要的东西?
答案 0 :(得分:2)
我建议使用ui-router
提供的多个命名视图的功能。您可以阅读更多相关信息here。基本上文档说明如下:
您可以为视图命名,以便每个视图可以有多个ui视图 模板。
如果您查看文档中的示例,则表明您的方案与示例之间存在相似之处,因为您希望动态填充其他views
(此处为命名视图)。
示例强>
我尝试在此JSFiddle中重新创建您的方案。
首先,我创建了一个abstract
状态,它提供了不同的views
类似区域,技能等。这是抽象状态的模板:
<div class="curriculum" ui-view="areas"></div>
<div class="curriculum" ui-view="skills"></div>
接下来,我创建了一个嵌套状态curriculo.main
,它声明了您需要的不同视图(区域,技能等)。每个视图都有自己的template
和controller
。请注意,嵌套状态具有resolve
,它最初从名为curriculo
的服务加载区域。如果您使用结算,请记住,解析关键字必须相对于不是视图的状态(使用多个视图时)。
基本上,服务负责业务逻辑,意味着获取区域,技能等。在JSFiddle中,我已经对HTTP结果进行了硬编码。用HTTP调用替换它并使用promises。由于每个命名视图都有自己的控制器,因此我们需要一种机制来通知更改,例如通知SkillsController
已加载技能。因此,我创建了一个简单的事件系统(subcribe-notify):
.factory('notifier', function($rootScope) {
return {
subscribe: function(scope, callback, eventName) {
var handler = $rootScope.$on(eventName, callback);
scope.$on('$destroy', handler);
},
notify: function(eventName, data) {
$rootScope.$emit(eventName, data);
}
};
});
然后SkillsController
可以订阅特定事件,如下所示:
notifier.subscribe($scope, function(event, data) {
$scope.skills = data;
}, 'onSkillsLoaded');
curriculo
服务电话(位于getSkills()
)notify
的末尾,并提供一个事件。在这种情况下,您在SkillsController
订阅的事件与<{1}}相同。
notifier.notify('onSkillsLoaded', result);
总而言之,这是我的小榜样背后的魔力。值得一提的是,您需要将最佳实践应用于代码,因为这只是为了重新创建您的场景。对于最佳实践,我建议John Papa Angular Style Guide。
更新1
我更新了我的示例以向您显示深层链接。我通过
模拟深层链接$state.go('.', {area: 2, skill: 5});
这样我可以激活某种状态。现在每个视图都有activate
函数。在这个函数中,我做了所有初始化的工作,例如,如果设置了查询参数,则选择区域。如您所知,您可以使用$state
服务访问参数。我不得不使用$timeout
来延迟区域控制器的初始化,因为订阅还没有完成。请尝试找到解决此问题的更好方法。也许您可以使用promises或在服务中注册每个控制器,如果所有控制器都已初始化,该服务将解析。
如果选择了任何内容,我还会使用go
和其他选项将notify
设置为false
。
$state.go('.', {area: area.id, skill: skillId ? skillId : undefined}, {notify: false});
如果notify
设置为false
,则会阻止控制器重新初始化。因此,您只能更新URL,并且不会发生状态更改。