AngularJS:无法使用 ui-route $state 获取 html5 模式网址

Posted

技术标签:

【中文标题】AngularJS:无法使用 ui-route $state 获取 html5 模式网址【英文标题】:AngularJS: can't get html5 mode urls with ui-route $state 【发布时间】:2013-06-30 21:52:55 【问题描述】:

我正在使用ui-router 进行状态管理,但我认为我的 .htaccess 重写规则有问题。使用 /#/account 样式网址时,我所有的状态都有效。现在我启用了 html5 模式,但我的应用程序没有像以前那样呈现。它似乎加载了我的 index.html 以及我所有的 js 和 css 文件等,但实际上并没有初始化任何状态。

这是我的文件夹结构:

root/
    app/
        components/
            angular/
            ...
        images/
        scripts/ 
            controllers/
            directives/
            ...
            app.js       
        styles/
        views/
        .htaccess
        ...

我的虚拟主机 DocumentRoot 指向我的app/

这是我的 app.js 和我的状态:

'use strict';

angular.module('appointeddPortalApp',  ['ngResource', 'ui.state', 'ui.compat', 'fundoo.services', 'ui.date', 'ngCookies'])
.config(function ($stateProvider, $routeProvider, $locationProvider, $httpProvider) 

    var access = routingConfig.accessLevels;

    delete $httpProvider.defaults.headers.common["X-Requested-With"];
    $httpProvider.defaults.useXDomain = true;
    $locationProvider.html5Mode(true);

    $stateProvider
    .state('root', 
        abstract: true,
        url: '',
        views: 
            'header': 
                templateUrl: 'views/partials/header.html'
            ,
            'search': 
                templateUrl: 'views/partials/search.html',
                controller: 'SearchCtrl'
            ,
            'main': 
                templateUrl: 'views/main.html',
                controller: 'MainCtrl'
            ,
            'footer': 
                templateUrl: 'views/partials/footer.html'
            ,
        ,
    )
    .state('root.home', 
        url: '',
        views: 
            'content': 
                templateUrl: 'views/home/index.html',
                controller: 'MainCtrl',
            
        ,
        access: access.anon
    )
    .state('root.about', 
        url: '/about',
        parent: 'root',
        views: 
            'content': 
                templateUrl: 'views/about.html',
                controller: 'StaticCtrl'
            ,
            'search@': 
        ,
        access: access.anon
    )
    .state('root.search', 
        url: '/search/:city/:category',
        views: 
            'content': 
                templateUrl: 'views/search.html',
                controller: 'SearchCtrl'
            
        ,
        access: access.anon
    )
    .state('root.salons_profile', 
        url: '/salons/id',
        views: 
            'content': 
                templateUrl: 'views/salons.profile.html',
                controller: 'SalonCtrl',
            ,
            'search@': 
        ,
        access: access.anon
    )
    .state('root.account', 
        url: '/account',
        abstract: true,
        views: 
            'content': 
                templateUrl: 'views/user/account.html',
                controller: 'AccountCtrl'
            
        ,
    )
    .state('root.account.info', 
        url: '',
        views: 
            'account_head': 
                templateUrl: 'views/user/account.head.html',
            ,
            'account_body': 
                templateUrl: 'views/user/account.my_appointedd.html',
            ,
        ,
        menus: 
            'account': 
                identifier: 'my_appointedd',
                class: 'active'
            
        ,
        access: access.user
    )
    .state('root.account.appointments', 
        url: '/appointments',
        views: 
            'account_head': 
                templateUrl: 'views/user/account.head.html',
            ,
            'account_body': 
                templateUrl: 'views/user/account.appointments.html',
            ,
        ,
        menus: 
            'account': 
                identifier: 'appointments',
                class: 'active'
            
        ,
        access: access.user
    )
    .state('root.account.details', 
        abstract: true,
        views: 
            'account_head': 
                templateUrl: 'views/user/account.head.html',
            ,
            'account_body': 
                templateUrl: 'views/user/account.details.html',
            ,
        ,
        access: access.user
    )
    .state('root.account.details.account', 
        url: '/details',
        views: 
            'right': 
                templateUrl: 'views/user/account.details.account.html',
            ,
        ,
        menus: 
            'account': 
                identifier: 'details',
                class: 'active'
            ,
            'settings': 
                identifier: 'account',
                class: 'active'
            
        ,
        access: access.user
    )
    .state('root.account.details.profile', 
        url: '/profile',
        views: 
            'right': 
                templateUrl: 'views/user/account.details.profile.html',
            ,
        ,
        menus: 
            'account': 
                identifier: 'details',
                class: 'active'
            ,
            'settings': 
                identifier: 'profile',
                class: 'active'
            
        ,
        access: access.user
    );


)
.run( [ '$location', '$state', '$stateParams', '$rootScope', '$cookies', 'Auth', function( $location, $state, $stateParams, $rootScope, $cookies, Auth)

    $rootScope.client_id = '51a741eb3152c3ae7e000103';
    $rootScope.$state = $state;
    $rootScope.$stateParams = $stateParams;
    $rootScope.$cookies = $cookies;

    $rootScope.$on('$stateChangeStart', function(event, toState, toParams, fromState, fromParams)
        if (!Auth.authorize(toState.access)) 
            if(Auth.isLoggedIn()) $state.transitionTo('root.account');
            else                  $state.transitionTo('root.home');
        
    );

这是我的重写代码,它位于 /app 的 .htaccess 中。我认为这可能是错误的。

<IfModule mod_rewrite.c>
  Options +FollowSymLinks 
  RewriteEngine On 
  RewriteBase / 
  RewriteRule ^(components|images|scripts|styles|views)($|/) - [L]
  RewriteRule ^(.*)$ index.html [L]
</IfModule>

【问题讨论】:

【参考方案1】:

如果在不允许编辑 Apache 配置的共享主机中工作,您可以在 .htaccess 文件中进行设置,以使 $locationProvider.html5Mode(true) 工作(正如 @Shanimal 在 @nfiniteloop 答案中指出的那样):

RewriteEngine on

RewriteBase /path/to/app #change this!

# Don't rewrite files or directories
RewriteCond %REQUEST_FILENAME -f [OR]
RewriteCond %REQUEST_FILENAME -d
RewriteRule ^ - [L]

# Rewrite everything else to index.html to allow html5 state links
RewriteRule ^ index.html [L]

别忘了在 HTML 中添加&lt;base href="/path/to/app/"&gt; &lt;head&gt;

【讨论】:

【参考方案2】:

我们的许多使用 html5mode 和 ui-router 的 Apache 用户都可以使用此配置。

<VirtualHost *:80>
    ServerName my-app

    DocumentRoot /path/to/app

    <Directory /path/to/app>
        RewriteEngine on

        # Don't rewrite files or directories
        RewriteCond %REQUEST_FILENAME -f [OR]
        RewriteCond %REQUEST_FILENAME -d
        RewriteRule ^ - [L]

        # Rewrite everything else to index.html to allow html5 state links
        RewriteRule ^ index.html [L]
    </Directory>
</VirtualHost>

另外请确保您不是&lt;base href&gt; 错误的受害者。请参阅ui-router FAQ 了解更多信息。

【讨论】:

嗨,nfiniteloop,看来我的问题是 错误!谢谢! 你摇滚。 +1。菜鸟...您可以将 &lt;Directory 节点内的所有内容放到根目录下的 .htaccess 中,您的网络主机也会产生相同的效果。干杯! 在drupal中当我设置这个规则时将如何设置500内部服务器错误请帮助 但是不是每条路线都丢失了,我总是被重定向到家吗?例如。 mypage.de/abc 将被重定向到 mypage.de/index.html 而不是 mypage.de/#/abc 这似乎不适用于子状态“admin.classes”。我得到一个 404 未找到。我确实将此规则添加到我的 htaccess 文件中:RewriteRule ^admin/(.*)$ /$1 [R,L]。当我在 /admin/classes 上重新加载页面时。我被路由到 /classes。

以上是关于AngularJS:无法使用 ui-route $state 获取 html5 模式网址的主要内容,如果未能解决你的问题,请参考以下文章

AngularJS:ui-router解析后无法访问控制器中的变量

尽管ui-route和provider似乎工作正常,但我无法在angularjs中加载视图......这是一段代码

Angularjs UI-route 为啥无法跳转到 test.html

在 AngularJs 中使用 UI-Router 更改导航菜单

使用 ui-router 和 Angularjs 自动滚动到顶部

使用AngularJS中的UI-Router将状态重定向到默认子状态