使用Angular、Express和Jade(使用html5mode)刷新特定页面

6
我正在尝试刷新页面并执行客户端路由,以打开ng-view内部的模板。
Index.jade
extends layouts/default

block content
  section(data-ng-view)
  script(type="text/javascript").
    window.user = !{user};

default.jade

doctype html
html(lang='en', xmlns='http://www.w3.org/1999/xhtml', xmlns:fb='https://www.facebook.com/2008/fbml', itemscope='itemscope', itemtype='http://schema.org/Product')
  include ../includes/head
body
  div(data-ng-include="'static/modules/core/views/core.header.view.html'", data-role="navigation")
  div(data-ng-include="'static/modules/core/views/core.index.view.html'", data-role="navigation")
  div(data-ng-include="'static/modules/core/views/core.menu.view.html'", data-role="navigation")
  div(data-ng-include="'static/modules/core/views/core.footer.view.html'", data-role="navigation")
  include ../includes/foot

服务器路由。
// Camera Routes
    app.get('/api/cameras', cameras.all);
    app.post('/api/cameras', auth.requiresLogin, cameras.create);
    app.get('/api/cameras/:cameraId', cameras.show);
    app.put('/api/cameras/:cameraId', auth.requiresLogin, auth.article.hasAuthorization, cameras.update);
    app.del('/api/cameras/:cameraId', auth.requiresLogin, auth.article.hasAuthorization, cameras.destroy);
    app.param('cameraId', cameras.camera);

    // Home route
    app.get('/', index.render);

express.js

/**
 * Module dependencies.
 */
var express = require('express');
var flash = require('connect-flash');
var helpers = require('view-helpers');
var config = require('./config');

module.exports = function(app, passport) {

    console.log('Initializing Express');

    app.set('showStackError', true);    

    //Prettify HTML
    app.locals.pretty = true;

    //Should be placed before express.static
    app.use(express.compress({
        filter: function(req, res) {
            return (/json|text|javascript|css/).test(res.getHeader('Content-Type'));
        },
        level: 9
    }));

    //Setting the fav icon and static folder
    app.use(express.favicon());
    app.use('/static',express.static(config.root + '/public'));

    //Don't use logger for test env
    if (process.env.NODE_ENV !== 'test') {
        app.use(express.logger('dev'));
    }

    //Set views path, template engine and default layout
    app.set('views', config.root + '/app/views');
    app.set('view engine', 'jade');

    //Enable jsonp
    app.enable("jsonp callback");

    app.configure(function() {
        //cookieParser should be above session
        app.use(express.cookieParser());

        // request body parsing middleware should be above methodOverride
        app.use(express.urlencoded());
        app.use(express.json());
        app.use(express.methodOverride());

        //express/mongo session storage
        app.use(express.session({ secret: '$uper$ecret$e$$ionKey'}));

        //connect flash for flash messages
        app.use(flash());

        //dynamic helpers
        app.use(helpers(config.app.name));

        //use passport session
        app.use(passport.initialize());
        app.use(passport.session());

        //routes should be at the last
        app.use(app.router);
        //Assume "not found" in the error msgs is a 404. this is somewhat silly, but valid, you can do whatever you like, set properties, use instanceof etc.

        app.all('/*', function(req, res, next) {
            res.render('index.jade', {'root': 'app/views/'});
        });

        app.use(function(err, req, res, next) {
            //Treat as 404
            if (~err.message.indexOf('not found')) return next();

            //Log it
            console.error(err.stack);

            //Error page
            res.status(500).render('500', {
                error: err.stack
            });
        });

        //Assume 404 since no middleware responded
        app.use(function(req, res, next) {
            res.status(404).render('404', {
                url: req.originalUrl,
                error: 'Not found'
            });
        });
    });
};

HTML5启用
//Setting HTML5 Location Mode
angular.module('mean').config(['$locationProvider',
    function($locationProvider) {
        $locationProvider.html5Mode(true);
        $locationProvider.hashPrefix("!");
    }
]);

客户端路由在此,我想在 ng-view 中显示此模板。
angular.module('mean').config(['$stateProvider',
function ($stateProvider) {
    $stateProvider.
        state('viewCamera', {
            url: "/cameras/:cameraId",
            templateUrl: 'static/modules/cameras/views/cameras.camera.view.html'
        });
}

]);

使用 ui-view 标签的索引视图

<section data-ng-controller="MapController" data-ng-init="find()">
    <div ui-view>
    </div>
    <div class="map-content" ng-class="{'map-content-left': cameraOpen != undefined}">
        <leaflet defaults="defaults" center="center" class="map"></leaflet>
    </div>
</section>

我的 HTML 头部
head
  base(href='/')

我想要什么?当我手动插入这个URL:localhost:3000/cameras/12,调用服务器并获取索引以调用客户端路由并在ng-view中打开模板。
问题是什么?当我在浏览器中插入此URL时,我会得到带有下载模式的index.jade。
我已经尝试过什么?
更改服务器路由为以下内容(显然会返回渲染的索引)。
  // Home route
    app.get('*', index.render);

但是客户端路由从未被调用。
有什么问题吗?
编辑1:
我的依赖版本。
"angular": "latest",
"angular-resource": "latest",
"angular-cookies": "latest",
"angular-mocks": "latest",
"angular-ui-utils": "0.0.4",
"angular-translate": "~2.5.2",
"angular-translate-loader-static-files": "~2.5.2",
"ngDialog": "~0.3.7",
"angular-leaflet-directive": "~0.7.10",
"leaflet.markercluster": "~0.4.0",
"angular-loading-bar": "~0.6.0",
"angular-ui-router": "~0.2.13"

我正在使用这里的Mean-Stack-Relacional:https://github.com/jpotts18/mean-stack-relational 编辑2:
我原本使用的是angular-route,所以我改成了ui-router来查看问题是否解决。
编辑3:
客户端路由核心。
//Setting up route
angular.module('mean').config(['$stateProvider', '$urlRouterProvider',
    function ($stateProvider, $urlRouterProvider) {
        $urlRouterProvider.otherwise("/");

        $stateProvider.
            state('login', {
                url: '/login',
                template: '',
                controller: 'SessionController',
                data: {
                    method: "login"
                }
            })
            .state('signin', {
                url: '/signin',
                template: '',
                controller: 'SessionController',
                data: {
                    method: "signin"
                }
            })
            .state('home', {
                url: '/',
                resolve: {
                    resetMap: function ($q, $location, $rootScope) {
                        $rootScope.$emit('rootScope:emit', '');
                    }
                }
            });
    }
]);

如果您正在使用1.3版本,请尝试将您的HTML5配置更改为$locationProvider.html5Mode({ enabled: true, requireBase: false });,@LeandroHoffmann。 - scniro
尝试使用 res.render('index', {'root': 'app/views/'});。您已经指定了Jade作为视图引擎。 - Scymex
抱歉,我正在编辑中,之前我使用的是angular-route,现在改用ui-router来看是否能解决问题,但结果仍然相同。 - Leandro Hoffmann
2
我认为你不能在ng-include内部拥有ui-view,请尝试将其移出。 - Scymex
哇塞,你太棒了!回答问题可以获得奖励! - Leandro Hoffmann
显示剩余18条评论
2个回答

5

@Scymex 帮我找到这个问题:

对于使用Jade的任何人,这是一个快速的坑: div(ui-view) 编译为 <div ui-view="ui-view"></div>. 你需要的是 div(ui-view="").

因此,你可以在ng-include中使用ui-view,但需要使用此技巧。

来源: https://github.com/angular-ui/ui-router/issues/679


2
你正在使用带有hashbang后备的HTML5路由。这意味着您希望设置服务器,以便将请求/cameras/12重定向到/#!/cameras/12。 然后服务器将呈现您的Angular应用程序,该应用程序将检测它要转到viewCamera状态,并在客户端上重新编写URL。
您可以通过向express应用程序添加以下中间件来实现此目标:
app.use(function (req, res, next) {
    res.set('Location', '/#!' + req.path)
       .status(301)
       .send();
});

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接