【问题标题】:In AngularJS how to render different items of a list independently在AngularJS中如何独立呈现列表的不同项目
【发布时间】:2013-05-19 18:37:43
【问题描述】:

我是 AngularJS 的新手,即使花了几个小时我也无法在互联网上找到以下问题的答案。

请随时提出更好的方法,我在下面尝试。

查看我的 AngularJS 代码:

<li ng-repeat="result in getResults()" ng-controller="resultController"> 
 <div class="name_style">
  {{result.name}}
 </div>

  <!--fetch more details for each result and set to $scope.resultDetail-->
 <div class="name_detail_style" ng-bind=getDetails(result.name) ng-controller="resultDetailController">
  {{resultDetail.image}}
  {{resultDetail.description}}
 </div>

</li>    

为简洁起见,我试图在上面进行简化。

我正在尝试分两部分呈现结果列表:

  1. getResuls() 调用休息服务以获取结果数组。

  2. 然后 getDetails(result) 进行另一个服务调用以获取特定结果的更多详细信息。

它运行得非常慢,因为 AngularJS 试图同时渲染名称和它的细节。我希望名称在可用时立即呈现,并在 getDetail() 服务调用有机会获得响应时呈现详细信息。

我不知道是否/如何使用此解决方案 How to load data asynchronously using AngularJS with SpringMVC?

如果您也需要查看控制器端代码,请告诉我。

EDIT 也添加控制器代码示例。请原谅手动重新创建以下代码中的任何拼写错误。

function resultController($scope, $http) {
    $scope.getResults = function() {

        $http({method: 'GET', url: resultURL=  timeout: maxTime})
            .success(function (data, status, headers, config) {
               console.log(data);
               $sope.result=data;     
            })

            .error(function (data, status, headers, config) {
                if (status == 0) {
                    serviceTimedoutError($scope, data, status, config);
                } else {
                    serviceFailure($scope, data, status, config);
                }
            })
    };

};



function resultDetailController($scope, $http) {
    $scope.getDetails = function(result) {
          resultDetailsURL=resultDetailsUR+"/"+result  
        $http({method: 'GET', url: resultDetailsURL=  timeout: maxTime})
            .success(function (data, status, headers, config) {
               console.log(data);
           $sope.resultDetails={"image":data["image"],"description":data["description"]};     
            })

            .error(function (data, status, headers, config) {
                if (status == 0) {
                    serviceTimedoutError($scope, data, status, config);
                } else {
                    serviceFailure($scope, data, status, config);
                }
            })
    };

};

【问题讨论】:

  • 您将模型直接设置为函数调用,这并不典型。 (我以前没见过这个)。大多数情况下,您会看到ng-repeat = "result in results",其中results 实际上是在$scope.results = getResults(); 等控制器中定义的。但是,您也应该发布一些控制器代码或工厂/服务代码,以便获得完整的答案。
  • 好的,也要发布控制器代码。

标签: javascript web-services twitter-bootstrap angularjs


【解决方案1】:

您不能(意味着真的不应该)在模板中引用本质上是 AJAX 调用包装函数的内容。没关系,这不是“角度方式”(模板不应该弄乱数据,而您的 ng-repeat 是调用 ajax 函数的原因),它会中断,因为您正在进行 AJAX 调用(每个调用一个返回数组中的元素!)每个渲染周期!

您应该能够(并且很可能希望)控制何时从后端/API 获取信息,并一直使用它,直到您想要刷新它/提交任何更改。所以,主要要做的就是改变:

<li ng-repeat="result in getResults()" ng-controller="resultController"> 

<li ng-repeat="result in myResults" ng-controller="resultController"> 

和 resultController 到:

function resultController($scope, $http) {
    $scope.getResults = function() {

        $http({method: 'GET', url: resultURL=  timeout: maxTime})
            .success(function (data, status, headers, config) {
               console.log(data);
               $sope.result=data;     
            })

            .error(function (data, status, headers, config) {
                if (status == 0) {
                    serviceTimedoutError($scope, data, status, config);
                } else {
                    serviceFailure($scope, data, status, config);
                }
            })
    };

    $scope.myResults = $scope.getResults();

};

它的作用是在控制器被实例化时一次调用 AJAX 请求。

然后您可以对 resultDetailController 执行相同的操作,但请考虑是否值得。仅当主要结果不太可能发生很大变化时(每次更改时,请求都会重复),或者细节代表大量数据,并且您确实需要快速显示结构时,才应该将这些调用分开,然后才是细节。

另外,请考虑仅在用户“打开它”等情况下才调用元素的详细信息。

编辑,回复下面的cmets

正如我所说,您应该真正将信息(模型,以及获取和更新它的 AJAX 请求)与模板和显示分开。也就是说,您需要决定什么是最好的:

  • 您可以预先获取所有信息,然后进行过滤(仅过滤显示的内容)或
  • 您可以从后端获取一组经过过滤的元素

在第二种情况下,您仍应控制 AJAX 调用发生的频率。例如,您可以观察过滤器变量(使用 $scope.$watch() )并在发生这种情况时调用 $http 服务:

(在结果控制器中:)

$scope.$watch("filterString", function(){
  $scope.myResults = $scope.getResults($scope.filterString);
}

我会注意到,每次您在过滤器“搜索框”中输入内容时,都会发出一个新请求(这可能会过度杀伤力,甚至会导致错误的结果 - 如果“beac”请求返回 例如在“海滩”请求之后)。一种可能的解决方案是在您键入时实现覆盖先前的超时(搜索仅在您停止键入后的 0.5 秒内开始)

$scope.$watch("filterString", function(){
  $scope.getResultsTimeout.cancel();
  $scope.getResultsTimeout = $timeout(
    function(){
      $scope.myResults = $scope.getResults($scope.filterString);
    },
    500);
}

【讨论】:

  • 我试图缩小有问题的代码示例,实际上,我的项目中的 getResults() 也有一些基于用户输入的过滤,并且每次都需要刷新以尊重用户的过滤参数。
  • 问题仍然存在 - 你需要能够告诉角度 何时 你想刷新(你真的不想每秒执行 30 多个请求!)我会编辑我的答案以包含一个示例。
  • 感谢您的编辑和回答。澄清一下,我认为 getResuls 在页面加载时只会被调用一次,但是 getDetails(result) 将被调用 30 多次,这是我提出的主要问题,并且想避免它。就我而言,“getDetails”是所有服务中最慢的,因为它需要在后端进行所有计算。而且,我仍然需要在屏幕上向用户显示每个结果的详细信息,因为没有该结果是无关紧要的。
  • 您似乎将从后端优化中受益(将结果记录为缓存信息等),但这只是一种感觉,超出了您的问题范围。您的初始代码是错误的,因为它导致多次发出相同的请求,而我的回答似乎解决了这个问题。除此之外,这是一个策略和计划的问题(动画来解释延迟?优先考虑最重要的请求?分页?)
【解决方案2】:

我在 http://plnkr.co/edit/nTI58uAkUfE3pw2yjy9q 创建了一个 plunk,它展示了如何使用服务和指令来实现您所说的结果。关键是在指令链接时,id 与指令相关联。然后使用 detailId 上的 $watch 来触发辅助调用。

要将它用于您的完整项目,您必须更新服务以使用 $http 或 $resource 调用从您的服务器获取内容。

【讨论】:

  • +1 用于代码和解释。虽然,不确定它是否能解决我的问题,但我也不知道如何在现有代码中使用指令。
  • 是否可以将一个包含 10 个 result.id 的数组一起发送到 getDetails()。因为 getDetails() 的服务可以接受多个逗号分隔格式的 resultid。这样,不会为每个结果调用 getDetails,并且性能将在可接受的范围内。我的项目列表范围是 10-30 个结果。所以在最坏的情况下 getDetails 只会被触发 3 次,而不是 30 次。
  • 在这种情况下,我会将列表发送到 get details 之类的函数,但是我不会让 getDetails 完成工作,而是让 $resource 查询获取集合,但仍然有不同的 get从内存变量(仍然来自服务)中提取每个细节的细节函数。
  • 您不一定需要该指令,但是您确实需要服务和控制器中的手表来执行后期绑定回调。
  • 哦,就如何使用指令而言,将它们视为只是包装块,以包含您重复执行的部分功能。他们在那里创建一种更语义化的代码创建方式。正如 Misko Hevry 所说,角度教浏览器新技巧。它可以做到这一点,但允许您创建独立的代码块(指令),这些代码块可以作用于您的应用程序并为您的应用程序创建新语法。
猜你喜欢
  • 1970-01-01
  • 2020-02-05
  • 1970-01-01
  • 1970-01-01
  • 2019-09-09
  • 2011-03-28
  • 1970-01-01
  • 2015-05-16
  • 2021-07-16
相关资源
最近更新 更多