更新模型和URL的正确方法是什么?

时间:2014-12-07 17:42:58

标签: angularjs url model routing

假设我在同一页面上有以下元素:

  1. 过滤器面板(类似于 http://www.imdb.com/search/name
  2. 基于过滤器选项的项目
  3. 我想实现以下逻辑:

    1. 网址应包含路径(/appliedOptionA/appliedOptionB
    2. 中应用的过滤器数据
    3. 当用户打开网站应用从网址获取过滤数据时,更新过滤器 面板和项目面板
    4. 当用户更改过滤器应用更新网址并刷新项目时
    5. 第一个想法:配置ng-router,获取过滤数据作为参数,将数据转换为模型,构建过滤器面板,加载项,构造项面板。 主要问题:当用户更改过滤器时应该如何工作?如果我更新URL,它将触发具有不同参数的相同控制器并重复该过程 - >获取过滤数据作为参数,将数据转换为模型,构建过滤器面板,项目等。我不需要它 - 我的模型和UI已经是最新的。

      我的问题:

      保持模型和URL同步的正确方法是什么? URL管理模型(ng-route)或模型更改管理URL(如何?)?

2 个答案:

答案 0 :(得分:1)

我的建议是使用angular-ui-router并使用ng-router代替angular-ui-router,因为"appCtrl"为您提供了更大的灵活性,在我看来,更容易使用。

鉴于您的“主要问题”,听起来您希望有一个应用程序控制器(让我们将其称为appCtrl)处理所有更改并对其模型进行必要的更改。这种方法的主要缺点是它迫使你在appCtrl内维护“filteredItems”模型,这不好玩,可能导致不必要的麻烦。接近它的一种更简单的方法是让另一个控制器处理对url的更改,而不是angular-ui-router本身。话虽如此,让我告诉你如何实现这一目标。

*警告:帖子很长! (但希望有帮助)*

正因为如此,我还创建了一个演示我即将讨论的所有内容,以防你“只想要代码”:

创建应用程序

由于我们正在创建一个全新的应用程序,让我们从创建和配置应用程序开始。

注意:请记住将var myApp = angular.module('myApp', ["ui.router"]); 脚本加载到您的应用程序中并添加依赖项。

app.js

app

现在我们有<body ng-app="myApp"></body> ,让我们使用ngApp directive将其添加到index.html。

的index.html

"filteredItems"

应用程序到位后,让我们看一下您在问题中解决的问题:

  • 网址应包含路径中应用的过滤器数据(/ appliedOptionA / appliedOptionB)
  • 当用户打开网站应用从网址获取过滤数据时,更新过滤器面板和项目面板
  • 当用户更改过滤器应用更新网址并刷新项目时

您要做的是创建state。实质上,基于url模式激活/停用状态。给定一个特定的模式,您可以告诉应用程序如何操作(使用控制器)和看起来像什么(使用模板)。在继续之前,请务必参考url routing,这将有助于网址模式。

我们需要:

  • 为州提供名称(home
  • 提供网址格式
  • 提供控制器
  • 提供templateUrl

让我们配置应用程序,以及:

  • 在网址不存在的情况下提供默认网址
  • 添加默认的filteredItems
  • 添加myApp.config(function($stateProvider, $urlRouterProvider){ // default url - used if url pattern is not recognized $urlRouterProvider.otherwise('/'); $stateProvider .state('home', { // default state url: '/' }) .state('filteredItems', { // give the state a name url: "/:appliedOptionA/:appliedOptionB", // provide the url pattern controller: 'FilteredItemsCtrl', // controller to use for this state templateUrl: "filteredItems.html" // url for the template }); });

app.js

appliedOptionA

我们现在已经配置了州的网址来获取参数(appliedOptionBfilteredItemsCtrl)。使用$stateParams service,我们可以创建itemService并负责过滤数据。

但在我们这样做之前,我们应该创建一项服务。使用Angular时, AVOID 使用控制器来维护数据,因为它们可以被创建/销毁。最佳做法是使用服务。话虽如此,让我们创建一个惊人的angular.module('myApp').factory('itemService', itemService); function itemService (){ var items = { appliedOptionA: [ 'Item 1', 'Item 2', 'Item 3' ], appliedOptionB: [ 'Item 4', 'Item 5', 'Item 6' ] }; function getItems (){ return items; } return { getItems: getItems } }

<强> itemService.js

FilteredItemsCtrl

华丽吧?我很高兴你这么想!

现在我们有了服务,我们可以创建itemService。我们还将新创建的FilteredItemsCtrl注入$stateParams,以便能够访问数据。

注意:请记住将angular.module('myApp').controller('FilteredItemsCtrl', filteredItemsCtrl); filteredItemsCtrl.$inject = ['$stateParams', '$scope', 'itemService']; function filteredItemsCtrl ($stateParams, $scope, itemService){ var items = itemService.getItems(); // get items from service // filter items $scope.appliedOptionA = items.appliedOptionA.filter(function (item){ if ($stateParams.appliedOptionA){ return item.toLowerCase().indexOf($stateParams.appliedOptionA) > -1 || item.indexOf($stateParams.appliedOptionA) > -1 } }); $scope.appliedOptionB = items.appliedOptionB.filter(function (item){ if ($stateParams.appliedOptionB){ return item.toLowerCase().indexOf($stateParams.appliedOptionB) > -1 || item.indexOf($stateParams.appliedOptionB) > -1 } }); } 服务作为依赖项注入!

filteredItemsCtrl.js

url: "/:appliedOptionA/:appliedOptionB"

当我们定义州的网址时,我们将其设置为:$stateParams。这意味着将使用appliedOptionA,appliedOptionB属性填充filteredItemsCtrl。这也意味着每次更改网址时,都会创建 <div> <div> <span>Filtered Option A Items:</span> <ul> <li ng-repeat="optionItemA in appliedOptionA"> {{ optionItemA }} </li> </ul> </div> <div> <span>Filtered Option B Items:</span> <ul> <li ng-repeat="optionItemB in appliedOptionB"> {{ optionItemB }} </li> </ul> </div> </div> ,因此您无需维护应用程序的模型!

在我们忘记之前,我们还需要为此状态创建模板。

filteredItems.html

ui-view

在创建state,filteredItemCtrl和视图的情况下,剩下的就是包含 <body ng-app="myApp" ng-controller="MyAppCtrl"> <div> <div> Applied Option A: <input ng-model="appliedOptionA" /> </div> <div> Applied Option B: <input ng-model="appliedOptionB" /> </div> <button type="button" ng-click="filter()">Search</button> </div> <!-- where the state template goes --> <div ui-view></div> </body> 指令,以便正确显示状态模板:

的index.html

{{1}}

这就是它的全部!对于这篇长篇文章感到抱歉,但希望您发现这篇文章内容丰富!如果您有任何问题,请告诉我!

答案 1 :(得分:0)

如果您希望搜索关键字反映在URL中(因此可以将它们加入书签并直接进行处理),我建议不要强制模型的每次更改(这都是在每次击键后),而是等待提交表格。然后你重写URL(通过$ location.path和/或$ location.search),ngRoute将启动。

NgRoute将(重新)加载/刷新页面,就像它是第一次一样,并且与包含搜索关键字的可直接寻址页面的想法相匹配。我不建议您在收到提交后立即获取数据,因为正如您所述,ngRoute将刷新页面。