问题 如何在ui-router中实现路径别名


我正试图找到一种方法在Angular.js中使用实现路由别名 ui-router

假设我有一个带网址的状态 article/:articleId 而我想拥有 /articles/some-article-title 重定向(内部)到 /article/76554 无需更改浏览器位置。

可以这样做吗? ui-router


2974
2018-05-23 13:23


起源



答案:


I.双重状态映射(控制器,视图的重用)

注意:这是原始答案,显示如何解决两个状态的问题。以下是另一种方法,对评论做出反应 海尔特

有一个 plunker 用工作的例子。假设我们有这两个对象(在服务器上)

var articles = [
  {ID: 1, Title : 'The cool one', Content : 'The content of the cool one',},
  {ID: 2, Title : 'The poor one', Content : 'The content of the poor one',},
];

我们想用URL作为

// by ID
../article/1
../article/2

// by Title
../article/The-cool-one
../article/The-poor-one

然后我们可以创建这个状态定义:

// the detail state with ID
.state('articles.detail', {
    url: "/{ID:[0-9]{1,8}}",
    templateUrl: 'article.tpl.html',
    resolve : {
      item : function(ArticleSvc, $stateParams) {

        return ArticleSvc.getById($stateParams.ID);
      },
    },
    controller:['$scope','$state','item',
      function ( $scope , $state , item){ 

        $scope.article = item;
    }],
  })

// the title state, expecting the Title to be passed
.state('articles.title', {
    url: "/{Title:[0-9a-zA-Z\-]*}",
    templateUrl: 'article.tpl.html',
    resolve : {
      item : function(ArticleSvc, $stateParams) {

        return ArticleSvc.getByTitle($stateParams.Title);
      },
    },
    controller:['$scope','$state','item',
      function ( $scope , $state , item){ 

        $scope.article = item;
    }],
  })

我们可以看到,诀窍在于 调节器 和 模板  (templateUrl) 是相同的。我们只是问服务 ArticleSvc 至 getById() 要么 getByTitle()。解决后,我们可以使用返回的项目...

有更多细节的plunker是 这里 

II。别名,基于原生 UI-Router 功能

注意:此扩展作出反应 海尔特 适当的评论

所以,有一个 UI-Router 用于路由别名的内置/本机方式。它被称为

$ urlRouterProvider - 。什么时候()

我创造了工作 在这里。首先,我们只需要  国家定义,但没有任何ID限制。

.state('articles.detail', {
    //url: "/{ID:[0-9]{1,8}}",
    url: "/{ID}",

我们还必须实现一些mapper,将title转换为id (别名映射器)。这将是新的文章服务方法:

var getIdByTitle = function(title){
   // some how get the ID for a Title
   ...
}

而现在的力量 $urlRouterProvider.when()

 $urlRouterProvider.when(/article\/[a-zA-Z\-]+/,
  function($match, $state, ArticleSvc) {

    // get the Title 
    var title = $match.input.split('article/')[1];
    // get some promise resolving that title
    // converting it into ID
    var promiseId = ArticleSvc.getIdByTitle(title);

    promiseId.then(function(id){

      // once ID is recieved... we can go to the detail
      $state.go('articles.detail', { ID: id}, {location: false}); 
    })

    // essential part! this will instruct UI-Router, 
    // that we did it... no need to resolve state anymore
    return true;
  }
);

而已。这个简单的实现会跳过错误,错误的标题......处理。但无论如何,预计会实施...... 在这里检查它


12
2018-05-25 07:43



这不是任何类型的别名,而只是两个看起来非常相似的状态配置(实际上重用了相同的模板) - Geert
@Geert感谢您的评论。你的观点是正确有效的。它帮助我扩展答案并展示另一种方式,如何解决“别名”需求。可以说,这可以为你提供更多...... 注意:非常感谢您的评论和勇敢。只有这种方法(留下评论)才有助于改善答案。惊人! - Radim Köhler
非常感谢!你的解决方案让我从今天的大量头部撞击和头发拉动中救了我:) - Your Filthy Rich Neighbor


答案:


I.双重状态映射(控制器,视图的重用)

注意:这是原始答案,显示如何解决两个状态的问题。以下是另一种方法,对评论做出反应 海尔特

有一个 plunker 用工作的例子。假设我们有这两个对象(在服务器上)

var articles = [
  {ID: 1, Title : 'The cool one', Content : 'The content of the cool one',},
  {ID: 2, Title : 'The poor one', Content : 'The content of the poor one',},
];

我们想用URL作为

// by ID
../article/1
../article/2

// by Title
../article/The-cool-one
../article/The-poor-one

然后我们可以创建这个状态定义:

// the detail state with ID
.state('articles.detail', {
    url: "/{ID:[0-9]{1,8}}",
    templateUrl: 'article.tpl.html',
    resolve : {
      item : function(ArticleSvc, $stateParams) {

        return ArticleSvc.getById($stateParams.ID);
      },
    },
    controller:['$scope','$state','item',
      function ( $scope , $state , item){ 

        $scope.article = item;
    }],
  })

// the title state, expecting the Title to be passed
.state('articles.title', {
    url: "/{Title:[0-9a-zA-Z\-]*}",
    templateUrl: 'article.tpl.html',
    resolve : {
      item : function(ArticleSvc, $stateParams) {

        return ArticleSvc.getByTitle($stateParams.Title);
      },
    },
    controller:['$scope','$state','item',
      function ( $scope , $state , item){ 

        $scope.article = item;
    }],
  })

我们可以看到,诀窍在于 调节器 和 模板  (templateUrl) 是相同的。我们只是问服务 ArticleSvc 至 getById() 要么 getByTitle()。解决后,我们可以使用返回的项目...

有更多细节的plunker是 这里 

II。别名,基于原生 UI-Router 功能

注意:此扩展作出反应 海尔特 适当的评论

所以,有一个 UI-Router 用于路由别名的内置/本机方式。它被称为

$ urlRouterProvider - 。什么时候()

我创造了工作 在这里。首先,我们只需要  国家定义,但没有任何ID限制。

.state('articles.detail', {
    //url: "/{ID:[0-9]{1,8}}",
    url: "/{ID}",

我们还必须实现一些mapper,将title转换为id (别名映射器)。这将是新的文章服务方法:

var getIdByTitle = function(title){
   // some how get the ID for a Title
   ...
}

而现在的力量 $urlRouterProvider.when()

 $urlRouterProvider.when(/article\/[a-zA-Z\-]+/,
  function($match, $state, ArticleSvc) {

    // get the Title 
    var title = $match.input.split('article/')[1];
    // get some promise resolving that title
    // converting it into ID
    var promiseId = ArticleSvc.getIdByTitle(title);

    promiseId.then(function(id){

      // once ID is recieved... we can go to the detail
      $state.go('articles.detail', { ID: id}, {location: false}); 
    })

    // essential part! this will instruct UI-Router, 
    // that we did it... no need to resolve state anymore
    return true;
  }
);

而已。这个简单的实现会跳过错误,错误的标题......处理。但无论如何,预计会实施...... 在这里检查它


12
2018-05-25 07:43



这不是任何类型的别名,而只是两个看起来非常相似的状态配置(实际上重用了相同的模板) - Geert
@Geert感谢您的评论。你的观点是正确有效的。它帮助我扩展答案并展示另一种方式,如何解决“别名”需求。可以说,这可以为你提供更多...... 注意:非常感谢您的评论和勇敢。只有这种方法(留下评论)才有助于改善答案。惊人! - Radim Köhler
非常感谢!你的解决方案让我从今天的大量头部撞击和头发拉动中救了我:) - Your Filthy Rich Neighbor