【问题标题】:Non-SPA with angular2带 angular2 的非 SPA
【发布时间】:2016-06-22 04:31:25
【问题描述】:

我开始使用 angular2(带有 express.js 后端)的目的是将页面的几个部分的控制权传递给 angular2 组件,但我最终意识到,当 angular2 控制整个区域时,系统会更有效。页。但是,我的应用程序不是 SPA,除了包含我的 angular2 根组件的选择器的路由之外,还有其他服务器呈现的路由。

我有2个问题,后面是代码sn-ps:

  1. 每当我加载一个服务器控制的路由,其服务器端渲染的模板不包含我的根组件的选择器<main-comp></main-comp>,angular2 基本上都会向控制台吐出说它没有任何地方可以初始化。我将所有 angular2 初始化代码放在整个应用程序的共享标头中。如果页面上根本不存在它的选择器,有没有办法告诉 angular2 根组件不要呈现自己?

  2. 呈现 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) {
    }
}

这里是&lt;head&gt; 元素:

<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>

【问题讨论】:

    标签: angular


    【解决方案1】:

    1) 我想您需要在调用 bootstrap() 之前手动检查,如果未找到选择器,则跳过 bootstrap()

    2) 使用&lt;base&gt; 标记或提供APP_BASE_HREF 设置基本URL 可能会解决这个问题。另见Angular 2 router no base href set

    【讨论】:

    • 谢谢@Gunter。我尝试了&lt;base&gt; 标签并没有看到任何区别,然后作为测试我尝试&lt;base href="/blah"&gt; 看看实际做了什么,当我点击由RouteConfig 控制的链接时,它在开头附加了“blah”每个角度路由,后跟服务器请求的整个 URL。在另一个问题上,我会看看在调用引导程序之前检查页面上的元素是否可行。还是觉得有点hacky。
    • 您还可以在github.com/angular/angular 中创建错误报告,以便为您所需的引导行为提供开箱即用的支持。
    【解决方案2】:

    对于第一个问题,我在调用引导方法之前在页面上添加了&lt;main-comp&gt; 是否存在的检查(感谢@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/'
            }
        });
    

    【讨论】:

      猜你喜欢
      • 2017-07-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-06-14
      • 2016-12-25
      • 1970-01-01
      • 2017-01-29
      相关资源
      最近更新 更多