当前位置: 首页 > 面试题库 >

Angular-ui.router:更新URL而无需刷新视图

鲜于喜
2023-03-14
问题内容

我有一个Angular SPA,它根据一些餐厅数据的不同部分提供了各种推荐列表和位置的Google
Map(请参阅m.amsterdamfoodie.nl)。我希望每个列表都有自己的URL。为了让Google抓取不同的列表,我将<a>标签用于offcanvas导航。

目前,<a>标签会导致视图刷新,这在地图上非常明显。

  • 我可以防止使用ng-click$event.preventDefault()(请参见下面的代码段),但是随后我需要实现一种更新浏览器URL的方法。
  • 但是,在尝试Angular $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代码:

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这里使用。我相信,我已正确理解您的挑战…有一个可行的例子。如果此套件不完全适合您,请从中获得启发

免责声明:我无法实现这一目标: 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

<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'

子视图main.criteria也确实注入到 布局 视图中。

其网址以符号 ^url : '^/criteria/:criteria/:value')开头,该符号允许/主斜杠而不是子斜杠双倍

还有一些控制器,它们在这里有点天真,但它们应该表明,后台可能是真实的数据加载(基于条件)。

这里最重要的是PARENT 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

.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子在这里



 类似资料:
  • 问题内容: 我正在使用$ _SESSION变量通过AJAX发送电子邮件(它们需要在不刷新页面的情况下发送),但是$ _SESSION变量不会自动更新,因此当它更改时,我需要刷新页面以更新变量。 是否可以不刷新而更新$ _SESSION变量? 这是我用来发送电子邮件的代码: 因此,基本上,如果$ _SESSION变量更改,则需要此AJAX电子邮件来识别它,而无需刷新。 谢谢你的帮助 问题答案: 当您

  • 问题内容: 我正在AngularJS中构建仪表板系统,但遇到通过设置URL的问题 在我们的仪表板中,我们有一堆小部件。单击它们时,每个视图都会显示一个更大的最大化视图。我们正在尝试设置深层链接,以允许用户使用最大化的小部件链接到仪表板。 目前,我们有2条路线看起来像和 当用户最大化窗口小部件时,我们使用来更新url ,但这会导致视图重新呈现。由于我们拥有所有数据,因此我们不想重新加载整个视图,我们

  • 问题内容: 我有一个网站需要更新状态。就像飞行一样,您要离开,巡航或着陆。我希望能够刷新状态而无需让观众拥有并重新加载整个页面。我知道有一种使用AJAX和jQuery的方法,但是我对它的工作原理没有任何了解。我也不希望他们单击​​按钮。如果有人知道该怎么做,我将不胜感激! 问题答案: 通常,如果您不知道某些事情是如何工作的,请寻找可以学习的示例。 对于此问题,请考虑 您可以看到使用jQuery很容

  • 问题内容: 我从数据库获取数据并将其显示在div中…我要做的是单击链接时应更改div的内容 一种选择是通过URL将参数传递给自身并重新加载页面… 我需要这样做而 无需重新加载\刷新 … 目的是当我单击任何链接时,div和php变量的内容无需刷新即可更新....这样 用户可以看到新数据 ,然后如果执行某些查询,它将在新变量上 ps我知道它将需要一些AJAX,但我不知道AJAX ..所以请以我可以学习

  • TL;DR使用AngularFirestore和离子/角度。我希望在用户设备(例如表单上的复选框)之间同步数据,而不会导致所有用户的整页刷新。 我是爱奥尼亚/Angular应用程序的快乐用户,该应用程序用于促进我管理的咖啡店的工作。我在应用程序中有一个现有的清单功能。 该应用程序是使用FireStore作为后端实现的,我使用的是AngularFirestore API。 我在咖啡馆里有几款运行该应

  • 问题内容: 我有一个抽象的基本模板,可根据用户类型加载导航。这部分适用于初始加载。问题是用户登录或注销后无法重新加载父templateProvider。我在这里尝试了重新加载父模板的解决方案,但是导航模板不受影响。有没有一种方法可以重新加载templateProvider,或者这样做的更好的方法?理想情况下,我不必将导航提供商添加到每个子路线。 路线: 尝试从github问题发出的控制器功能: 问