构建一个Angular应用程序,我是使用ng-controller和自定义指令构建应用程序的粉丝,例如:
<nav ng-controller="NavController"></nav>
<date-picker></date-picker>
我喜欢这些模式,因为它们具有声明性,并且非常容易理解 - 您确切地知道在哪里寻找支持逻辑。
另一方面,使用ng-view,甚至ui-router插件(在我看来)抽象出一些功能并使其更难阅读。
但是,我的首选模式在以逻辑方式响应应用程序范围内的URL更改时给我一个问题。我希望UI的每个部分都能对URL更改做出适当的响应,但我不知道在哪里放置代码。我假设我有两个选择:
我无法弄明白该怎么做。
选项一让我完全控制,但我无法利用ng-route - 解析参数等。在检查URL更改时,我真的必须自己动手。< / p>
使用选项二,我无法引用任何控制器,因为它们已经被声明了!
更广泛地说,我担心的是,没有立即找到解决方案表明我必须错误地思考问题。这根本错了吗?
编辑:为了避免疑问,我非常谈论SPA,更具体地说,这是我试图做的事情:
<nav ng-controller="NavController"><!-- more HTML here --></nav>
<div ng-controller="VideoController"><!-- more HTML here --></div>
<div ng-controller="CommentController" ng-show="Active"><!-- more HTML here --></div>
现在,假设我导航到:&#34; / video /:key /&#34; - 我希望VideoController获取视频密钥,并执行加载视频所需的操作。我希望NavController突出显示哪个菜单项是活动的等等。
如果我导航到&#34; / video /:videokey / comment&#34; - 我希望VideoController加载视频,并使用NavController突出显示哪个是活动的,还有CommentController加载评论/出现在视频中等等。
这个想法我无法理解 - 响应两个控制器中的URL更改,每个控制器负责单页应用程序中UI的单独部分。
答案 0 :(得分:4)
这不是您正在寻找的答案,但这是您需要听到的答案( 意见消失! 您将花费大量时间围绕自己的布局和路线创意构建SPA。如果可能的话,我不会感到惊讶 - 如果您在适当的范围内发出事件并让子控制器监听状态更改事件,您可以定义不同的控制器,这些控制器对状态更改做出不同的响应,显示和隐藏其内容,并更新这些内容反映当前对象模型(/ things / 1到things / 2到things / 2 / edit或者其他)。 这几乎就是ui-router的工作原理,除了不是在主页面中嵌入顶级html内容,而是使用ui-view指令基本上处理部分和控制器。 在一天结束时,这样做,你将复制ui-router目前所做的大约50%。如果你很幸运,它将和ui-router一样好用。如果你不是,它会以有趣的方式出错。 你将拥有一个huuuuuge单页面应用程序,它将很难调试。如果您在一个没有包含模板的顶级html页面中拥有所有内容,则您将无法轻松分离关注点或分解行为。其他一些开发人员无法跟进这项工作,并且使用未终结标签的细微错误可能更难找到。另外:与框架作斗争的所有时间都可以用于使应用程序工作。
答案 1 :(得分:2)
正如您建议使用ngRoute,您可以将$rootParams
- 服务注入您的控制器并获取所有当前参数。如果您还需要ngRoute选择的当前控制器,您也应该注入$route
- 服务。有关如何使用这些服务的更多详细信息,请参阅example in the ngRoute documentation - 或提供角度代码的(最小)版本,以便根据您的用例提供示例。
BTW:如果SPA中也有不同的视图和/或布局(例如不仅仅是视频),您可以使用ngRoute的ng-view指令为所有这些不同的布局设置视口。这样,每个布局都可以拥有自己的模板和特定于布局的控制器,可以重用通用控制器和指令(例如用于注释)。我再次需要更多代码来为此提供一个有意义的示例。
答案 2 :(得分:1)
对于你想做的事,我看到了三个选择。
$rootScope
将控制器绑在一起;在这里保留您的URL变量。当他们改变时,您的控制器可以做出相应的反您可以在此处使用$broadcast
和$emit
来传递消息,或者您只需观看$rootScope
变量。听起来好像你想避免在每个控制器中放置路由逻辑 - 这很好 - 但是你必须找到一些方法来指定你想要的行为。如果我打算尝试从头开始,我想我更喜欢发布/订阅路线,我自己;我更喜欢在提供商中封装这样的东西(因为它是模块化的,可以很容易地重复使用)。
尽管如此,我同意其他答案 - 只需简单地使用ngRoute
或uiRouter
即可。通过这样做,您可以在一个地方(沿着路由参数)设置路由,并使用嵌套的控制器/视图或指令。实际上,您可以考虑将Video和Coments对象转换为Angular指令。
答案 3 :(得分:0)
尝试使用angular-ui路由器。它可以是您需要的图书馆。 Github项目: https://github.com/angular-ui/ui-router
答案 4 :(得分:0)
我猜你不是在谈论SPA,单页申请。
所以问题是,
您是否希望对多个页面使用相同的$routeProvider
,并为当前页面路径提供正确的控制器?
可悲的是,url路径和angularjs路径路径不同,你不能使用url路径到AngularJS路径路径。
为了解决这个问题。这是我的想法 我们可以从绝对头部确定angularjs路径路径。
在您的应用中,使用$window.location.href
或$window.location.pathname
在您的其他区块中使用该路径。
以下是代码和演示:http://plnkr.co/edit/OS38E38J11FeDS1hyHde?p=preview
angular.module('myApp', ['ngRoute'])
.controller('MainController', function($scope) {
$scope.pageName = "main page";
})
.controller('Page1Controller', function($scope) {
$scope.pageName = "page1";
})
.controller('Page2Controller', function($scope) {
$scope.pageName = "page2";
})
.config(function($routeProvider, $windowProvider) {
var otherwiseFunc = function() {
var absPath = $windowProvider.$get().location.href;
console.log('absPath', absPath);
var redirectTo = absPath.match(/path1/) ? '/page1' :
absPath.match(/path2/) ? '/page2' :
'/main';
return {
redirectTo: redirectTo
}
};
$routeProvider
.when('/main', {templateUrl: 'partial.html',controller: 'MainController'})
.when('/page1', {templateUrl: 'partial.html',controller: 'Page1Controller' })
.when('/page2', {templateUrl: 'partial.html',controller: 'Page2Controller' })
.otherwise(
otherwiseFunc()
);
});
答案 5 :(得分:0)
可能最简单的方法就是创建一个处理网址的服务。
该服务将返回一组与每个控制器相关的参数,这些参数取决于URL。例如,它会有一个属性Video.id
来表示视频ID,Nav.id
来表示导航链接等。
服务本身非常简单 - 获取URL,将其拆分为参数,最难的部分是分离哪个控制器所需的参数(根据上述示例中的规则构建对象)。
示例网址:/video/mySupercoolVideo/comment
服务返回类似:
{
video: "mySupercoolVideo",
nav: "comment",
comments: true
// other url-related data here
}
这是一个非常简单和基本的例子(导航和评论似乎多余,我没有扩展任何顶级属性,所以没有video.id
之类的东西),显然你可以扩展/优化这一点。
每个控制器都会在开始时检查URL状态,并根据响应进行操作。
如果您愿意,您也可以使用包装器控制器,因此您不必为每个控制器返回相同的数据,而只需使用该数据填充一个$ rootScope变量。