带 angular2 的非 SPA
Posted
技术标签:
【中文标题】带 angular2 的非 SPA【英文标题】:Non-SPA with angular2 【发布时间】:2016-06-22 04:31:25 【问题描述】:我开始使用 angular2(带有 express.js 后端)的目的是将页面的几个部分的控制权传递给 angular2 组件,但我最终意识到,当 angular2 控制整个区域时,系统会更有效。页。但是,我的应用程序不是 SPA,除了包含我的 angular2 根组件的选择器的路由之外,还有其他服务器呈现的路由。
我有2个问题,后面是代码sn-ps:
每当我加载一个服务器控制的路由,其服务器端渲染的模板不包含我的根组件的选择器<main-comp></main-comp>
,angular2 基本上都会向控制台吐出说它没有任何地方可以初始化。我将所有 angular2 初始化代码放在整个应用程序的共享标头中。如果页面上根本不存在它的选择器,有没有办法告诉 angular2 根组件不要呈现自己?
呈现 angular2 根组件的服务器端路由是 /writing
,特定博客文章的 angular2 路由 URL 类似于 /writing/2016/03/post
。但是,每当我直接浏览到 URL 时,System.js 都会尝试加载相对于该位置的 app/boot,即/writing/2016/03/app/boot
,这显然会失败并显示 404。我认为这是因为我的服务器控制了/writing
相对于向服务器请求的基本 URL 的路由和角度负载。因此,我知道的唯一解决方案是将我的应用程序变成一个单服务器路由为'/'
的 SPA,这需要对前端进行大量重写。我该如何解决这个问题?
这是我的根组件:
@Component(
selector: 'main-comp',
template: '<router-outlet></router-outlet>',
providers: [TagService, PostService, BlogStateService],
directives: [ROUTER_DIRECTIVES, BlogComponent]
)
@RouteConfig([
path: '/writing/...', name: 'Blog', component: BlogComponent
])
export class AppComponent
constructor(private _blogState : BlogStateService,
private _postService : PostService)
这里是<head>
元素:
<head>
<script src="/js/jquery.min.js"></script>
<script src="/js/modernizr-2.6.2-respond-1.1.0.min.js"></script>
<!-- Angular Dependencies -->
<script src="/app/node_modules/angular2/bundles/angular2-polyfills.js"></script>
<script src="/app/node_modules/es6-shim/es6-shim.js"></script>
<script src="/app/node_modules/systemjs/dist/system.src.js"></script>
<script src="/app/node_modules/moment/moment.js"></script>
<script>
System.config(
packages:
app:
format: 'register',
defaultExtension: 'js'
,
moment:
main: 'moment.js',
type: 'cjs',
defaultExtension: 'js'
,
map:
moment: '/app/node_modules/moment/'
);
</script>
<script src="/app/node_modules/rxjs/bundles/Rx.js"></script>
<script src="/app/node_modules/angular2/bundles/angular2.dev.js"></script>
<script src="/app/node_modules/angular2/bundles/http.dev.js"></script>
<script src="/app/node_modules/angular2/bundles/router.dev.js"></script>
<script>
System.import('app/js/boot').then(null, console.error.bind(console));
</script>
<base href="/">
</head>
【问题讨论】:
【参考方案1】:1) 我想您需要在调用 bootstrap()
之前手动检查,如果未找到选择器,则跳过 bootstrap()
。
2) 使用<base>
标记或提供APP_BASE_HREF
设置基本URL 可能会解决这个问题。另见Angular 2 router no base href set
【讨论】:
谢谢@Gunter。我尝试了<base>
标签并没有看到任何区别,然后作为测试我尝试<base href="/blah">
看看实际做了什么,当我点击由RouteConfig
控制的链接时,它在开头附加了“blah”每个角度路由,后跟服务器请求的整个 URL。在另一个问题上,我会看看在调用引导程序之前检查页面上的元素是否可行。还是觉得有点hacky。
您还可以在github.com/angular/angular 中创建错误报告,以便为您所需的引导行为提供开箱即用的支持。【参考方案2】:
对于第一个问题,我在调用引导方法之前在页面上添加了<main-comp>
是否存在的检查(感谢@Gunter 的想法)。
对于上面的第二个问题,我在 system.js 配置中添加了引导文件的路径,如下所示,这样 system.js 就不会加载相对于请求 URL 的 app/boot。
System.config(
packages:
app:
format: 'register',
defaultExtension: 'js'
,
moment:
main: 'moment.js',
type: 'cjs',
defaultExtension: 'js'
,
map:
app: '/app', //<----------added this line
moment: '/app/node_modules/moment/'
);
【讨论】:
以上是关于带 angular2 的非 SPA的主要内容,如果未能解决你的问题,请参考以下文章
ObjectDataSource 未能找到带参数的非泛型方法
使用带参数方式新增或修改可为空的非字符串类型数据到oralce数据库
如何使用文本掩码中的 angular2 createNumberMask 用小数格式化百分比