【问题标题】:return object from Function to ng-repeat in AngularJS在AngularJS中将对象从函数返回到ng-repeat
【发布时间】:2016-03-06 14:01:39
【问题描述】:

我正在尝试将对象从函数返回到 ng-repeat:

<ul ng-controller="Users" ng-repeat="user in users">
    <li ng-controller="Albums" ng-repeat="album in getAlbumList(user.name)">
        {{album.title}}
    </li>
</ul>

.controller('Albums', ['$scope','Imgur', function($scope, Imgur) {
    $scope.getAlbumList = function(user) {
        Imgur.albumList.get({user:user},    
            function(value) {
                return value.data;
                console.log('success');
            },
            function(error) {
                console.log('something went wrong');
            }
        );
    }
}]);

.factory('Imgur', function($resource, $http) {
    return {
        albumList : $resource('https://api.imgur.com/3/account/:user/albums'),
        album : $resource('https://api.imgur.com/3/account/:user/album/:id')
    }
});

但是,这种方法在每次页面加载时都会使我的浏览器崩溃。

这样做的正确方法是什么?

【问题讨论】:

    标签: javascript angularjs


    【解决方案1】:

    所以,你有 ng-repeat="album in getAlbumList(user.name)",这是一个 Angular 表达式。 ng-repeat 所做的是在每个摘要上评估 getAlbumList(user.name)。这就像视图中的任何其他表达式一样,例如 ng-show 或其他任何表达式,并且这些表达式始终都会被评估。如果您的表达式计算数百次的速度很慢,那么您不应该在这样的表达式中使用它。

    您在这里拥有的是该函数中的 Ajax 调用。即使您以某种方式有一个阻塞的同步 Ajax 调用,它也会太慢几个数量级。表达式应该只访问手头的数据,或者运行简单的代码来排序和过滤。他们不应该尝试进行 Ajax 调用。

    但这是假设它是同步 Ajax,但事实并非如此。该表达式只是调用getAlbumList 并假设结果是一个数组并将其用于ng-repeat。该函数什么也不返回,所以它返回undefined,而你什么也得不到。

    因此,要回答您的问题,您应该做的是,在作用域上放置一个空数组,从 ng-repeat 使用它,然后通过 Ajax 填充它。 Angular 的美妙之处在于,数据一旦出现,就会在视图中“弹出”。这是一些视图代码:

    <ul>
      <li ng-repeat="album in albums">{{album.title}}</li>
    </ul>
    

    还有一些控制器代码:

    $scope.albums = [];
    Imgur.albumList.get({user:user},
        function(value) {
            $scope.albums = value.data;
            console.log('success');
        },
        function(error) {
            console.log('something went wrong');
        }
    );
    

    这基本上是您已经拥有的代码,只是不是从函数中运行,而是直接在控制器的构造函数中运行。

    编辑

    我认为您的根本误解是认为从 ngResource 回调返回的内容又会从包含函数 (getAlbumList) 中返回。事实并非如此。包含函数运行,不返回任何内容,然后在您的回调运行后,返回一些内容,但没有人使用该返回值。

    【讨论】:

    • +1 这是一个非常有用的解释,为什么这是错误的方法。谢谢!
    【解决方案2】:
    <ul ng-controller="Users">
         <li ng-repeat="user in users">
           <ul ng-controller="Albums" ng-init="getAlbumList(user.name)">
              <li ng-repeat="album in albums">
               {{album.title}}
              </li>
           </ul>
         <li>
    </ul>
    
    
    .controller('Albums', ['$scope','Imgur', function($scope, Imgur) {
        $scope.getAlbumList = function(user) {
            Imgur.albumList.get({user:user},    
              function(value) {
                    $scope.albums = value.data;
                    console.log('success');
              },
              function(error) {
                  console.log('something went wrong');
              }
          );
        }}]);
    

    试试这个。如果没有,那么检查这个问题 Reusable components in AngularJS

    【讨论】:

    • 如果可能的话,当您的主控制器加载到对象图中时,如果可能的话,在一次服务器调用中返回整个数据集,您以后可以在不进行额外调用的情况下进行遍历。
    • 当我 console.log 在进入$scope.getAlbumList 之后立即使用ng-init 在页面加载时没有注销。我阅读了您关于可重用组件的另一篇文章。对于这样的事情,使用指令而不是工厂有什么缺点?
    • 我做了一些进一步的改变。指令还用于创建可重用的“小部件”或添加交互性或修改 DOM 元素。 Factory 用于创建封装业务逻辑或进行服务器调用的服务。
    • 该更新有效。您能否在此下提供另一个示例,使用相同的上下文到可重用的东西中:)?那个方法还支持双向绑定吗?
    • 好的,我会在今天晚些时候做。我强烈建议您阅读指令文档docs.angularjs.org/guide/directive
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-03-17
    相关资源
    最近更新 更多