首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >更新模型和URL的正确方法是什么?

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

Stack Overflow用户
提问于 2014-12-07 17:42:57
回答 2查看 604关注 0票数 0

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

  1. 过滤器面板(类似于http://www.imdb.com/search/name)
  2. 基于筛选器选项的项

我想实现以下逻辑:

  1. URL应包含路径中应用的筛选器数据(/appliedOptionA/appliedOptionB)
  2. 当用户打开站点应用程序从URL获取筛选数据时,更新筛选面板和项目面板
  3. 当用户更改时,筛选、应用程序更新、URL和刷新项

第一个想法:配置ng-路由器,获取过滤器数据作为param,将数据转换为模型,构造过滤器面板,加载项目,构造项目面板。主要问题:当用户更改筛选器时,它应该如何工作?如果我要更新URL,它将触发相同的控制器与不同的param,并重复过程->获取过滤器数据作为param,将数据转换为模型,构造过滤器面板,项目等。我不需要它-我的模型和UI已经是最新的。

我的问题是:

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

EN

回答 2

Stack Overflow用户

发布于 2014-12-07 21:41:08

我的建议是使用角用户界面路由器而不是ng-router,因为angular-ui-router提供了更多的灵活性,而且在我看来更容易使用。

考虑到您的“主要问题”,听起来您希望有一个应用程序控制器(我们将其称为"appCtrl")来处理所有更改并对其模型进行必要的更改。这种方法的主要缺点是它迫使您在appCtrl中维护“appCtrl”模型,这并不有趣,可能会导致不必要的头痛。一种更简单的方法是让另一个控制器来处理对url的这些更改,而不是appCtrl本身。话虽如此,让我向你展示你是如何做到这一点的。

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

正因为如此,我还创建了一个演示,展示了我将要讨论的一切,以防您“只想要teh codez":

创建应用程序

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

注意:请记住将angular-ui-router脚本加载到应用程序中,并添加依赖项。

app.js

代码语言:javascript
复制
var myApp = angular.module('myApp', ["ui.router"]);

现在我们有了app,让我们使用ngApp指令将其添加到index.html中。

index.html

代码语言:javascript
复制
<body ng-app="myApp"></body>

在应用程序就位之后,让我们看看您在问题中处理的问题:

  • URL应该在路径中包含应用的过滤器数据(/appliedOptionA/appliedOptionB)
  • 当用户打开站点应用程序从URL获取筛选数据时,更新筛选面板和项目面板
  • 当用户更改时,筛选、应用程序更新、URL和刷新项

您想要做的是创建一个状态。本质上,状态是基于url模式激活/停用的。给定特定的模式,您可以告诉应用程序如何操作(使用控制器)和外观(使用模板)。在继续之前,请确保引用url路由,这将有助于使用url模式。

我们需要:

  • 给州一个名字("filteredItems")
  • 提供一个url模式
  • 提供控制器
  • 提供一个templateUrl

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

  • 如果url不存在,则提供默认url路由。
  • 添加默认的home状态
  • 添加filteredItems状态

app.js

代码语言:javascript
复制
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
    });
});

我们现在已经将状态的url配置为接受参数(appliedOptionA和appliedOptionB)。使用$stateParams service,我们可以创建一个filteredItemsCtrl,并让它负责过滤掉数据。

但在我们这么做之前,我们应该创造一个服务。在使用角时,避免使用使用控制器来维护数据,因为它们可以创建/销毁。最佳实践是使用服务。话虽如此,让我们创建一个惊人的itemService

itemService.js

代码语言:javascript
复制
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
    }
}

很漂亮对吧?我很高兴你也这么想!

现在我们有了一个服务,我们可以创建FilteredItemsCtrl了。让我们还将新创建的itemService注入到FilteredItemsCtrl中,以便它能够访问数据。

注意:请记住将$stateParams服务作为依赖项注入!

filteredItemsCtrl.js

代码语言:javascript
复制
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
      }
    });
}

当我们定义状态的url时,我们将其设置为:url: "/:appliedOptionA/:appliedOptionB"。这意味着$stateParams将使用appliedOptionA、appliedOptionB属性填充。这也意味着每次URL更改时,都会创建一个新的 filteredItemsCtrl,因此,您不必维护应用程序的模型!

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

filteredItems.html

代码语言:javascript
复制
<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>

创建了状态、filteredItemCtrl和视图之后,剩下的就是包含ui-view指令,以便状态模板正确显示:

index.html

代码语言:javascript
复制
 <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>

这就是一切!很抱歉,很长的帖子,但希望你找到了这方面的信息!如果你有任何问题,请告诉我!

票数 1
EN

Stack Overflow用户

发布于 2014-12-07 19:05:22

当您希望搜索关键字在URL中得到反映(以便它们可以被书签和直接寻址)时,我建议不要强制对模型进行每次更改(在每次击键之后),而是等待表单的提交。然后重写URL (通过$location.path和/或$location.search),ngRoute就会启动。

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

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/27345683

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档