Angular-ui.router:在不刷新视图的情况下更新URL。

14 浏览
0 Comments

Angular-ui.router:在不刷新视图的情况下更新URL。

我有一个Angular SPA,它基于餐厅数据的不同切分,提供了各种推荐列表和Google地图位置(请参见m.amsterdamfoodie.nl)。我希望每个列表都有自己的URL。为了让Google爬取不同的列表,我使用了标签作为离屏导航。\n目前标签会导致视图刷新,而地图上的刷新非常明显。\n

    \n

  • 我可以使用ng-click$event.preventDefault()来阻止这种情况发生(请参见下面的代码片段),但接下来我需要实现一种更新浏览器URL的方法。
  • \n

  • 但是,尝试使用Angular的$state或浏览器的history.pushstate时,我会触发状态变化和视图刷新...!
  • \n

\n因此,我的问题是如何更新模型和URL,但不刷新视图?(另请参见Angular/UI-Router - How Can I Update The URL Without Refreshing Everything?)\n我尝试了很多方法,目前有以下HTML代码:\n

Budget

\n在控制器中:\n

this.action = ($event) ->
    $event.preventDefault()
    params = $event.target.href.match(/criteria\/(.*)\/(.*)$/)
    # 似乎会导致视图刷新
    # history.pushState({}, "page 2", "criteria/"+params[1]+"/"+params[2]);
    # 似乎会导致视图刷新
    # $state.transitionTo 'criteria', {criteria:params[1], q:params[2]}, {inherit:false}
    updateModel(...)

\n我认为正在发生的事情是,我正在触发$stateProvider的代码:\n

angular.module 'afmnewApp'
.config ($stateProvider) ->
  $stateProvider
  .state 'main',
    url: '/'
    templateUrl: 'app/main/main.html'
    controller: 'MainCtrl'
    controllerAs: 'main'
  .state 'criteria',
    url: '/criteria/:criteria/:q'
    templateUrl: 'app/main/main.html'
    controller: 'MainCtrl'
    controllerAs: 'main'

\n可能的一个线索是,如果我加载http://afmnew.herokuapp.com/criteria/cuisine/italian,则在导航时视图会刷新,而如果我加载http://afmnew.herokuapp.com/,则没有刷新,但也没有更新URL。我完全不明白为什么会发生这种情况。

0
0 Comments

Angular-ui.router: 在不刷新视图的情况下更新URL

问题的原因是如果子视图在父视图内部,两个控制器将共享相同的作用域。所以你可以在父视图中放置一个虚拟(或必要的)ui-view,该视图将由子视图填充。然后在父控制器中插入一个$scope.loadChildData = function(itemID){..blabla..};方法,在子控制器加载时将调用该方法。因此,当用户点击<a ui-sref="childState({itemID: 12})">bla</a>时,只有子控制器和子视图将被刷新。然后,您可以使用必要的参数调用父作用域函数。

解决方法是在一个没有与视图关联的控制器中使用div标签包装地图。不使用作用域继承,但是将所有关键数据保存在一个服务中,控制器可以随时访问。

0
0 Comments

Angular-ui.router: Update URL without view refresh问题的出现原因是想要在不刷新视图的情况下更新URL。解决方法是使用UI-Router。

根据之前的讨论,我们可以使用UI-Router来解决这个问题。下面给出了一个工作示例。如果这个示例不完全满足需求,请将其作为一些灵感。

所以,这里有一个状态定义(我们只有两个状态):

$stateProvider
.state('main', {
    url: '/',
    views: {
        '@' : {
            templateUrl: 'tpl.layout.html',
            controller: 'MainCtrl',
        },
        'right' : { templateUrl: 'tpl.right.html',}, 
        'map' : {
            templateUrl: 'tpl.map.html',
            controller: 'MapCtrl',
        },
        'list' : {
            templateUrl: 'tpl.list.html',
            controller: 'ListCtrl',
        },
    },
})
.state('main.criteria', {
    url: '^/criteria/:criteria/:value',
    views: {
        'map' : {
            templateUrl: 'tpl.map.html',
            controller: 'MapCtrl',
        },
        'list' : {
            templateUrl: 'tpl.list.html',
            controller: 'ListCtrl',
        },
    },
});

这是我们的主要`tpl.layout.html`:

我们可以看到,主状态会定位到主状态的嵌套视图,例如`'right'`。子视图`main.criteria`也会注入到`layout`视图中。它的URL以符号`^`开头,允许主路由有`/`,并且子路由没有重复的斜杠。

这里还有控制器,它们有点简单,但是它们应该显示出后台可以加载真实数据的情况(基于条件)。

最重要的是,父控制器`MainCtrl`创建了`$scope.Model = {}`。这个属性将(通过继承)在父控制器和子控制器之间共享。这就是为什么这一切会起作用的原因。

这应该给出一些关于如何使用UI-Router提供的功能的想法。

检查上述示例,[这里](http://plnkr.co/edit/iQUU6F?p=preview)是一个工作示例。

如果我们不想重新创建地图视图,我们可以从子状态定义中省略它:

.state('main.criteria', {
    url: '^/criteria/:criteria/:value',
    views: {
        //'map' : {
        // templateUrl: 'tpl.map.html',
        // controller: 'MapCtrl',
        //},
        'list' : {
            templateUrl: 'tpl.list.html',
            controller: 'ListCtrl',
        },
    },
});

现在,地图视图只会接收模型中的更改(可以被监视),但是视图和控制器不会重新渲染。

另外,这里还有另一个使用`controllerAs`的示例,[点击这里](http://plnkr.co/edit/y0GzHv?p=preview)。

.state('main', {
    url: '/',
    views: {
        '@' : {
            templateUrl: 'tpl.layout.html',
            controller: 'MainCtrl',
            controllerAs: 'main',
        },
        ...
    },
})
.state('main.criteria', {
    url: '^/criteria/:criteria/:value',
    views: {
        'list' : {
            templateUrl: 'tpl.list.html',
            controller: 'ListCtrl',
            controllerAs: 'list',
        },
    },
});

最后,这里还有一个[链接](http://plnkr.co/edit/y0GzHv?p=preview)。

快速问题:在MainCtrl中创建Model是否重要?到目前为止,我一直使用一个共享的Factory。

请原谅之前的问题。我的主要兴趣不是刷新地图,而是在模型更改时让控制器删除和重新创建标记(通过在'right'面板上单击引起)。我修改了你的plnkr示例,并在每次加载MapCtrl时添加了一个console.log消息,这相当于视图重新加载(我认为),但它一直在进行。这让我有些担心,但可能是因为我将模型保存在一个Factory中(我在上面的评论中提到过)。

我稍后会给你答复,我保证。

我目前正在考虑将地图本身放入主视图中,但是通过子视图创建标记。

0
0 Comments

问题原因:在使用Angular-ui.router进行页面跳转时,虽然可以通过$state.go方法实现URL的更新,但是在使用浏览器的前进和后退功能时,页面会重新加载。

解决方法:通过设置$state.go方法的第三个参数,将notify和reload属性设置为false,即可实现URL的更新而不刷新页面。

整理后的文章如下:

Angular-ui.router: 更新URL而不刷新视图的解决方法

在使用Angular-ui.router进行页面跳转时,我们经常需要更新URL来保持页面的状态。然而,使用$state.go方法更新URL会导致页面重新加载,这在某些情况下可能会带来一些问题。

解决这个问题的方法是设置$state.go方法的第三个参数,将notify和reload属性设置为false。这样,在使用$state.go方法更新URL时,页面不会重新加载。

下面是一个示例代码:

$state.go('my.state', {id:data.id}, {notify:false, reload:false});
//And to remove the id from the url:
$state.go('my.state', {id:undefined}, {notify:false, reload:false});

这段代码中,我们使用$state.go方法更新URL,同时将notify和reload属性设置为false,以实现URL的更新而不刷新页面。

需要注意的是,这个解决方法只适用于angular-ui-router版本为0.2.18及以上的情况。如果你使用的是旧版本的angular-ui-router,可能需要升级到0.2.18以上的版本才能使用这个解决方法。

更多关于$state API的信息,可以查看http://angular-ui.github.io/ui-router/site/#/api/ui.router.state.$state。

通过设置$state.go方法的第三个参数,将notify和reload属性设置为false,可以实现在更新URL时不刷新页面。这个解决方法适用于angular-ui-router版本为0.2.18及以上的情况。

然而,需要注意的是,在一些特定情况下,仍然可能会存在一些与这个问题相关的次要问题。如果你遇到了这些问题,可以参考相关的github讨论,或者查看最新版本的UI-Router文档,以获取更多信息和解决方案。

0