2015-02-07 79 views
5

我试图让Thing工厂发出HTTP请求,并能够在我的控制器中使用响应。为什么我需要在我的工厂使用angular.copy?

  1. 在我的工厂我必须做angular.copy(data, arr)。只是做arr = data不起作用。为什么是这样? angular.copy()只是a)删除arr中的所有内容,b)通过data进行迭代并将内容分配给arr。与arr = data唯一的区别是arr指向data而不是data的新副本。为什么会这样?为什么不arr = data.slice(0)工作(从我个人理解,这几乎是一样的angular.copy)

  2. 什么是实现我的目标的最好方法是什么?(使用工厂正常)

main.html中

<div class="container"> 

<div class="page-header"> 
    <h1>Test App</h1> 
</div> 

<ul> 
    <li ng-repeat="thing in things">{{thing.name}}</li> 
</ul> 

</div> 

main.controller.js

'use strict'; 

angular.module('testApp') 
    .factory('Thing', function($http) { 
    var arr = []; 
    return { 
     things: arr, 
     get: function() { 
     $http.get('/api/things').success(function(data) { 
      angular.copy(data, arr); // this works 
      // arr = data; but this doesn't 
      // arr = data.slice(0); and neither does this 

     }); 
     } 
    }; 
    }) 
    .controller('MainCtrl', function ($scope, Thing) { 
    Thing.get(); 
    $scope.things = Thing.things; 
    }); 
+0

angular.copy适用于对象或数组,数据是一个对象吗?顺便说一句,你应该利用提升和提取你的匿名函数到命名函数中,并简单地将函数名称传递给工厂和控制器方法。使得更容易找出模块的组件。 – Robert 2015-02-07 05:35:59

+0

'data'是一个对象数组。 – 2015-02-07 05:41:36

+1

它可以工作,因为arr(数组)是一个引用,并且您需要保留引用才能使范围绑定起作用。否则,你只是用一个新的引用覆盖arr--这是与最初绑定到作用域的引用完全不同的对象。 – pixelbits 2015-02-07 05:49:14

回答

7

你的问题是没有关系的角度,而是为JavaScript。

var arr = [] // arr is a pointer to an empty array 
var things = arr // things is a pointer to the same empty array 
arr = data // now arr points to data, but things still points to the empty array 

您可以通过运行下面的代码说服的是自己:

var a = [1]; 
var b = a; 
a = [2]; 
// Now if you console.log a and b, a === [2] and b === [1] 

但是,如果你操纵的对象

var a = { data: 1 } 
var b = a; 
a.data = 2; 
// Now a.data and b.data are the same: 2 
a = { data: 3 }; 
// Here we changed a, not its property, so a and b are not the same anymore 
// a.data === 3 but b.data === 2 

的财产,如果你明白,有很多如何解决你的问题,如:

angular.module('testApp') 
    .factory('Thing', function($http) { 
    var obj = {}; 
    return { 
    things: obj, 
    get: function() { 
     $http.get('/api/things').success(function(data) { 
     obj.data = data; 
     }); 
    } 
    }; 
}) 

并在您的HTML使用things.data

或者如果您不想使用对象属性,而是直接使用数组,而不是替换指针,则只需更新数组的内容(因此arr仍指向同一数组):

angular.module('testApp') 
    .factory('Thing', function($http) { 
    var arr= []; 
    return { 
    things: arr, 
    get: function() { 
     $http.get('/api/things').success(function(data) { 
     for (var i in data) { 
      arr[i] = data[i]; 
     } 
     }); 
    } 
    }; 
}) 
+0

啊我事后觉得很愚蠢。谢谢! – 2015-02-07 15:13:07

0

发生这种情况是因为您将arr设置为某个数组的新实例,而不是使用当前的实例。这里是一个比喻,你在做什么:

var foo = function() { 
    this.test = 'hello'; 
    console.log(this.test); 
}; 

foo = function() { 
    this.test = 'other'; 
    console.log(this.test); 
}; 

console.log(foo()); // outputs other 

angular.copy而不是做这样的事情:

// foreach item in the source (in this case data) 
arr.push({ 
    my: "value" 
});