我有一个Angular SPA,它根据一些餐厅数据的不同部分提供了各种推荐列表和位置的Google Map(请参阅m.amsterdamfoodie.nl)。我希望每个列表都有自己的URL。为了让Google抓取不同的列表,我将<a>标签用于offcanvas导航。
<a>
目前,<a>标签会导致视图刷新,这在地图上非常明显。
ng-click
$event.preventDefault()
$state
history.pushstate
因此,我的问题是 如何在不刷新视图的情况下更新模型和URL? 我已经尝试了很多方法,目前有这个html
<a href="criteria/price/1" class="btn btn-default" ng-click="main.action($event)">Budget</a>
在控制器中:
this.action = ($event) -> $event.preventDefault() params = $event.target.href.match(/criteria\/(.*)\/(.*)$/) # seems to cause a view refresh # history.pushState({}, "page 2", "criteria/"+params[1]+"/"+params[2]); # seems to cause a view refresh # $state.transitionTo 'criteria', {criteria:params[1], q:params[2]}, {inherit:false} updateModel(...)
而且,我认为正在发生的事情是我正在触发$stateProvider代码:
$stateProvider
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'
一个可能的线索是,如果我加载例如下面的代码,例如http://afmnew.herokuapp.com/criteria/cuisine/italian,则浏览时视图会刷新,而如果我加载http://afmnew.herokuapp.com/没有刷新,但没有URL更新。我完全不知道为什么会这样。
根据我们之前的讨论,我想给您一些想法,如何在UI- Router这里使用。我相信,我已正确理解您的挑战…有一个可行的例子。如果此套件不完全适合您,请从中获得启发
UI- Router
免责声明:我无法实现这一目标: http ://m.amsterdamfoodie.nl/,但原理在该示例中应该类似
因此,有一个状态定义 (我们只有两个状态)
$stateProvider .state('main', { url: '/', views: { '@' : { templateUrl: 'tpl.layout.html', controller: 'MainCtrl', }, 'right@main' : { templateUrl: 'tpl.right.html',}, 'map@main' : { templateUrl: 'tpl.map.html', controller: 'MapCtrl', }, 'list@main' : { 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
tpl.layout.html
<div> <section class="main"> <section class="map"> <div ui-view="map"></div> </section> <section class="list"> <div ui-view="list"></div> </section> </section> <section class="right"> <div ui-view="right"></div> </section> </div>
如我们所见,主状态确实针对主状态的这些嵌套视图: “ viewName @ main ”,例如'right@main'
'right@main'
子视图main.criteria也确实注入到 布局 视图中。
main.criteria
其网址以符号 ^ (url : '^/criteria/:criteria/:value')开头,该符号允许/主斜杠而不是子斜杠双倍
url : '^/criteria/:criteria/:value'
/
还有一些控制器,它们在这里有点天真,但它们应该表明,后台可能是真实的数据加载(基于条件)。
这里最重要的是PARENT MainCtrl创建 $scope.Model = {} 。(由于继承)此属性将在父级和子级之间共享。这就是为什么这一切都会起作用的原因:
MainCtrl
$scope.Model = {}
app.controller('MainCtrl', function($scope) { $scope.Model = {}; $scope.Model.data = ['Rest1', 'Rest2', 'Rest3', 'Rest4', 'Rest5']; $scope.Model.randOrd = function (){ return (Math.round(Math.random())-0.5); }; }) .controller('ListCtrl', function($scope, $stateParams) { $scope.Model.list = [] $scope.Model.data .sort( $scope.Model.randOrd ) .forEach(function(i) {$scope.Model.list.push(i + " - " + $stateParams.value || "root")}) $scope.Model.selected = $scope.Model.list[0]; $scope.Model.select = function(index){ $scope.Model.selected = $scope.Model.list[index]; } })
这应该使我们了解如何使用UI-Router为我们提供的功能:
在工作示例中,在此处检查以上摘录
扩展:这里有新的矮人
如果我们不想重新创建地图视图,则可以从子状态def中省略该视图:
.state('main.criteria', { url: '^/criteria/:criteria/:value', views: { // 'map' : { // templateUrl: 'tpl.map.html', // controller: 'MapCtrl', //}, 'list' : { templateUrl: 'tpl.list.html', controller: 'ListCtrl', }, }, })
现在,我们的地图“视图”将仅接收模型中的更改(可以观察到),但视图和控制器不会被重新渲染
此外,还有另一种plunker http://plnkr.co/edit/y0GzHv?p=preview它使用controllerAs
controllerAs
.state('main', { url: '/', views: { '@' : { templateUrl: 'tpl.layout.html', controller: 'MainCtrl', controllerAs: 'main', // here }, ... }, }) .state('main.criteria', { url: '^/criteria/:criteria/:value', views: { 'list' : { templateUrl: 'tpl.list.html', controller: 'ListCtrl', controllerAs: 'list', // here }, }, })
可以这样使用:
<h4>{{main.hello()}}</h4> <h4>{{list.hello()}}</h4>
最后一个pl子在这里