在 .run 在路由中从 Angularjs 中的 url 中删除 #

Posted

技术标签:

【中文标题】在 .run 在路由中从 Angularjs 中的 url 中删除 #【英文标题】:Removing # from url in Angularjs while having .run in routes 【发布时间】:2016-03-04 00:38:18 【问题描述】:

这是我在 AngularJS 中的 app.js 路由文件

var app = angular.module('myApp', ['ngRoute', 'ngAnimate', 'toaster']);
app.config(['$routeProvider',
    function ($routeProvider) 
        $routeProvider.
                when('/login', 
                    title: 'Login',
                    templateUrl: 'resources/views/layouts/loginUser.php',
                    controller: 'authCtrl'
                )
                .when('/', 
                    title: 'Login',
                    templateUrl: 'resources/views/layout/login.php',
                    controller: 'logoutCtrl'
                )
                .when('/reset', 
                    title: 'Reset Password',
                    templateUrl: 'resources/views/layouts/forgetPassword.php',
                    controller: 'authCtrl'
                )
                .when('/invalidtoken', 
                    title: 'Login',
                    templateUrl: 'resources/views/layout/invalidtoken.php',
                    controller: 'authCtrl',
                    role: '0'
                )

                //$locationProvider.html5Mode(true);
    ])


        .run(function ($rootScope, $location, Data, $http) 
            $rootScope.$on("$routeChangeStart", function (event, next, current) 
                     var nextUrl = next.$$route.originalPath;

                    if (nextUrl == '/signin' || nextUrl == '/login' || nextUrl == '/verify' || nextUrl == '/register' || nextUrl == '/registered' || nextUrl == '/reset' || nextUrl == '/resetdone' || nextUrl == '/registersuccess')
                    
                        $location.path(nextUrl);
                    
                     else
                       

                        $location.path('/');
                          
            );
        );

这里我使用 .run 来处理一些请求。

我想从 url 中删除 # 以使 url 更漂亮,

所以我这样做是为了按照建议 here 删除 #

app.config(['$routeProvider', '$locationProvider'
    function ($routeProvider, $locationProvider) 

在最后一行

$locationProvider.html5Mode(true);

但是应用程序没有发生任何事情,它仍然在 url 中有 #。

即使我尝试过this 方式

我怎样才能做到这一点?

更新:

如果我这样做了

.run(function ($rootScope, $location, Data, $http, $locationProvider) 

在最后一行

$locationProvider.html5Mode(true);

我收到了这个错误

Error: $injector:unpr
Unknown Provider

我尝试了很多方法,但都没有奏效。

更新 2:

或者任何人都可以建议一个 angularjs 示例的链接,它提供了在 url 中没有 # 的示例?

【问题讨论】:

你用什么浏览器? @PetrAveryanov Google Chrome 最新版是我用的 @PetrAveryanov 还有其他类似的可能性吗? 你把 放在页眉了吗? @Vivek 是的,我试过了,但它没有帮助我 【参考方案1】:

为什么要使用 .run() ?将<base href="/" /> 添加到您的<head> 或身体的开头(第一行),然后匹配您的 .run() 的逻辑,试试这个(.otherwise("/path") 到您的$routeProvider):

var app = angular.module('myApp', ['ngRoute', 'ngAnimate', 'toaster']);
app.config(['$routeProvider', '$locationProvider',
    function ($routeProvider, $locationProvider) 
        $routeProvider.
                when('/login', 
                    title: 'Login',
                    templateUrl: 'resources/views/layouts/loginUser.php',
                    controller: 'authCtrl'
                )
                .when('/', 
                    title: 'Login',
                    templateUrl: 'resources/views/layout/login.php',
                    controller: 'logoutCtrl'
                )
                .when('/reset', 
                    title: 'Reset Password',
                    templateUrl: 'resources/views/layouts/forgetPassword.php',
                    controller: 'authCtrl'
                )
                .when('/invalidtoken', 
                    title: 'Login',
                    templateUrl: 'resources/views/layout/invalidtoken.php',
                    controller: 'authCtrl',
                    role: '0'
                )
. otherwise("/");
           $locationProvider.html5Mode(true);
    ]);

如果你仍然遇到问题,我推荐https://github.com/angular-ui/ui-router

更新:

你的index.html

<!DOCTYPE html>
<html lang="en" ng-app="myApp">
<head>
        <meta charset="utf-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width,initial-scale=1">
        <title>Green Hopping</title>
        <link rel="shotcut icon" type="favicon.ico" href="public/images/favicon.ico" />
        <link rel="icon" type="favicon.ico" href="public/images/favicon.ico" />
        <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.2/angular.min.js"></script>
        <script src="https://code.angularjs.org/1.4.2/angular-route.min.js"></script>

    </head>
    <body ng-cloak="">
      <base href="/">
        <div data-ng-view="" id="ng-view" class="slide-animation"></div>
    </body>

    <script>
      var app = angular.module('myApp', ['ngRoute']);
        app.config(['$routeProvider', '$locationProvider',
            function ($routeProvider, $locationProvider) 
                $routeProvider.
                        when('/', 
                            title: 'Home',
                            templateUrl: 'home.html',
                            controller: 'homeCtrl'
                        )
                        .when('/login', 
                            title: 'Login',
                            templateUrl: 'login.html',
                            controller: 'authCtrl'
                        )
                        .when('/logout', 
                            title: 'Logout',
                            templateUrl: 'logout.html',
                            controller: 'logoutCtrl'
                        )
                        .when('/dashboard', 
                            title: 'Dashboard',
                            templateUrl: 'dashboard.html',
                            controller: 'dashboardCtrl'
                        )          
                        .otherwise('/');              
                        $locationProvider.html5Mode(true);
            ])
        .run(function ($rootScope, $location, $http, loginSrv) 
            $rootScope.$on("$routeChangeStart", function (event, next, current) 
                    var nextUrl = next.$$route.originalPath;
                    var orUseUrl = $location.path();
                    console.log(nextUrl);
                    if (nextUrl === '/logout')loginSrv.logout();
                    if (nextUrl === '/login')loginSrv.login();
                    if (loginSrv.loggedin === false)  $location.path('/');  
                    else  $location.path(nextUrl); 
            );
        );
        app.service("loginSrv",function()
          var ls= this;
          ls.loggedin = false;
          ls.logout = function()
            ls.loggedin = false;
          
          ls.login = function()
            ls.loggedin = true;
          
        );
        app.controller("homeCtrl",function($scope, loginSrv)
          $scope.loggedin = loginSrv.loggedin;
        )     
        app.controller("dashboardCtrl",function($scope, loginSrv)
          $scope.loggedin = loginSrv.loggedin;
        )                    
        app.controller("authCtrl",function($scope, loginSrv)
          $scope.loggedin = loginSrv.loggedin;
        )
        app.controller("logoutCtrl",function($scope, loginSrv)
          $scope.loggedin = loginSrv.loggedin;
        )        
    </script>

</html>

所有其他模板都是这样。复制粘贴以下home.htmllogin.htmldashboard.htmllogout.html。 Plunker 将无法显示客户端路由的问题。尝试这个。这是完整的功能代码。

<div>
    <div><a href="/">Home</a> | 
    <a href="/login">Login</a> | 
    <a href="/dashboard">Dashboard</a> | 
    <a href="/logout">Logout</a></div>

    <div> This is from the home/login/dashboard/logout Controller. Loggedin: loggedin</div>
</div>

【讨论】:

UI Router 中有一些方法,如.onEnterresolve.onExit,您可以使用这些方法在进入或退出 url 时执行操作。它让生活更轻松。 但我想在某些情况下同时使用 .run,这不可能吗? 您无法从您的网址中删除#,并且根据您的.run() 逻辑,如果"/wrongurl" 它转到"/"。这可以由.otherwise("/") 直接完成,我提供的代码将完成您给定代码所做的所有事情。这不会与.html5Mode(true)&lt;base href="/"&gt; 发生冲突。为什么要使用 .run() 来实现该逻辑。如果你想在输入 url 时做一些其他的逻辑,那么为什么不在.run() 中使用$locationChangeStart event & path([path]) method(in $location)。 https://docs.angularjs.org/api/ng/service/$location。这些在我提到的ui.router 中变得很容易。看看吧。 如果我的代码对你正在使用的运行逻辑有帮助,请告诉我。 嘿,如果我这样做,我会得到空白页,并且什么都没有显示:(你能帮我吗【参考方案2】:

尝试改变:

$locationProvider.html5Mode(true);

收件人:

$locationProvider.html5Mode(
   enabled: true,
   requireBase: false
);

【讨论】:

【参考方案3】:

您不能在.run 中注入$locationProvider,因为提供程序仅适用于.config

This answer should help 但你会遇到 2 个问题:

    您需要在$locationProvider.html5Mode(true) 之前进行检查,因为它不适用于 IE 10 或更早版本。

    if(window.history && window.history.pushState)
        $locationProvider.html5Mode(true);
     
    

    只有在用户在 url 中输入 # 时删除它才能起作用,即如果用户键入 app/#/login,它将变为 app/login。但是,如果用户将更改后的 url app/login 加入书签或复制到浏览器中,他将收到错误消息,因为服务器不知道角度路由,因为它只是客户端。在我上面链接的线程中,您可能会找到一些有关如何解决此问题的 cmets。

【讨论】:

我没有在 Internet Explorer 中尝试,我在 chrome 中尝试,但这种情况不起作用,我尝试将它放在 .run 内部和外部 :( 您是否添加了 在这个答案***.com/a/32620370/3716153 中? 是的,我在 index.html 文件中添加了相同的内容 如果你有teamviewer,可以看看我的代码吗? 不看代码就很难找出问题所在。您是否将上述行放在 .config 中?您是否收到任何控制台错误?【参考方案4】:

您是否偶然收到 404 错误?每当您将模式更改为 html5history 时,您必须告诉 Web 服务器始终返回索引页面,无论请求什么 URL。正如角度文档在这里所说: https://docs.angularjs.org/guide/$location

使用此模式需要在服务器端重写 URL,基本上您必须重写所有指向应用程序入口点的链接(例如 index.html)。在这种情况下,要求&lt;base&gt; 标记也很重要,因为它允许 Angular 区分作为应用程序基础的 url 部分和应由应用程序处理的路径。

您是否尝试过这样做并正确配置它? 还请记住,您必须指定应用程序的基本条目 href 才能像

一样工作
  <base href="/" />

【讨论】:

你的意思是处理 .htaccess ? 是的,我想是的 - 没有在 Apache 服务器上工作,所以你必须自己检查如何做。【参考方案5】:

问题是它缺少服务注入。 所以在配置部分尝试注入 $locationProvider 如下所示。

app.config(['$routeProvider', '$locationProvider',
function ($routeProvider, $locationProvider) 
    $routeProvider.
            when('/login', 
                title: 'Login',
                templateUrl: 'resources/views/layouts/loginUser.php',
                controller: 'authCtrl'
            )
            .when('/', 
                title: 'Login',
                templateUrl: 'resources/views/layout/login.php',
                controller: 'logoutCtrl'
            )
            .when('/reset', 
                title: 'Reset Password',
                templateUrl: 'resources/views/layouts/forgetPassword.php',
                controller: 'authCtrl'
            )
            .when('/invalidtoken', 
                title: 'Login',
                templateUrl: 'resources/views/layout/invalidtoken.php',
                controller: 'authCtrl',
                role: '0'
            )

            $locationProvider.html5Mode(true);
])

【讨论】:

不,当我尝试这个时,# 没有被删除:(【参考方案6】:

使用 html5mode,您必须在 html 文件中指定基本 url,例如,

<base href="/">

一些链接供您参考,

https://docs.angularjs.org/error/$location/nobase

https://scotch.io/quick-tips/pretty-urls-in-angularjs-removing-the-hashtag

【讨论】:

$locationProvider 在你的配置函数中丢失了,你还需要服务器端路由来获得你想要的东西。背后的原因是当 locaitionchagnestart 时,它会查找 url 并通过你一个新的错误,所以为了避免这个错误,你需要实现服务器端路由。 即使我尝试添加 locationProvider.. 它对我不起作用。你能帮我吗【参考方案7】:

您似乎无法手动从 href 中删除 hash-bang (#),这会导致您的路由器出现故障,因为 hashbangs 使浏览器无法处理您的状态以便将获取请求发送到端点。浏览器不会通过 #/route 触发 get 请求,而它会通过 /route 触发,除非您在 html5 模式下使用您的 url 提供程序。对于 html5 模式,将以下行添加到您的 app.config 函数中:

$locationProvider.html5Mode(true).hashPrefix('!')

【讨论】:

以上是关于在 .run 在路由中从 Angularjs 中的 url 中删除 #的主要内容,如果未能解决你的问题,请参考以下文章

AngularJs Run块$ stateChangeStart未被触发

angular run()运行块

在我的 laravel 4 和 angularjs 应用程序中从一条路线重定向到另一条路线

IFrame 中的 AngularJS run() 方法不会在 iframe 重新加载时重新运行

如何在 AngularJs 中从 HTML 转换 JavaScript 代码

如何在angularjs中从模板html调用指令