ngResource 中的虚拟属性

Posted

技术标签:

【中文标题】ngResource 中的虚拟属性【英文标题】:Virtual attributes in ngResource 【发布时间】:2014-07-25 03:37:32 【问题描述】:

是否可以向 ngResource 添加虚拟属性? 我创建了这样的服务

app.factory('Person', ['$resource', function($resource) 

  return $resource('api/path/:personId', 
    personId: '@_id'
      , 
        update: 
          method: 'PUT'
        
      );
])

Person 有一个属性name 和一个属性surname。 我想通过添加虚拟属性 fullname 返回 resource.name + resource surname 来检索 fullname。 我知道我可以将它添加到控制器中,但是将它添加到服务中会使其更便携。 我试过这样的东西

app.factory('Person', ['$resource', function($resource) 

  return $resource('api/path/:personId', 
    personId: '@_id'
      , 
        update: 
          method: 'PUT'
        ,
    fullname: function(resource)
      return resource.name + ' ' + resource.surname;
    
  );
 );
])

但它不起作用。

【问题讨论】:

【参考方案1】:

Khanh TO 让我找到了可行的答案,但是,正如in this Angular ticket 所解释的,在拦截器中,您必须处理并返回response.resource 而不是response

这是一个解决方案(适用于 Angular 1.4):

app.factory('Person', ['$resource', function($resource) 

return $resource(
    'api/path/:personId',
    personId: '@_id',
    
        update: method: 'PUT',
        get: 
            method: 'GET',
            isArray: false,
            interceptor: 
                response: function(response) 
                    var resource = response.resource;
                    resource.fullname = resource.name + ' ' + resource.surname;
                    return resource;
                
            
        
    );
]);

【讨论】:

【参考方案2】:

您可以尝试 intercepting 来自 Person 资源的响应并增加响应。像这样:

app.factory('Person', ['$resource', function($resource) 
  function getFullName()
      return this.name + ' ' + this.surname;
  ;

  return $resource('api/path/:personId', 
    personId: '@_id'
      , 
        update: 
          method: 'PUT'
        ,
        'get': method:'GET', isArray:false,interceptor:
              'response': function(response) 
                  response.fullname = getFullName; //augment the response with our function
                  return response;
               
         
      );
]);

【讨论】:

【参考方案3】:

如果您只需要派生属性进行显示,您可以创建一个显示过滤器,而不是用冗余数据加载您的模型:

app.filter('personFullName', function() 
  return function(person) 
    return person.name + " " + person.surname;
  ;
)

然后在你的模板中引用过滤器:

<div>
  <p>person | personFullName</p>
  <p>- should match -</p>
  <p>person.name person.surname</p>
</div>

【讨论】:

这个解决方案很有趣,但我想我更愿意将虚拟属性保留在模型中,这样我就可以在多个视图中访问它,而不必处理每个视图中的过滤器。 【参考方案4】:

根据文档,$resource 返回一个构造函数。您可以利用构造函数的常用prototype 添加成员,即:

var Person = $resource('api/path/:personId', 
            personId: '@_id'
        , 
            update:  method: 'PUT' 
        ); // same as the 1st snippet from the question

Person.prototype.xxxx = ...;

return Person; // from your Angular service

在前面的示例中,xxxx 可以是原型中通常允许的任何内容。如果您想要的实际上是派生属性,即始终反映namesurname 属性的JS 属性,那么您需要一个支持Object.defineProperty() 的相当新的浏览器并将上面的Person.prototype 行替换为:

Object.defineProperty(
    Person.prototype,
    "fullname",
    get: function()  return this.name + " " + this.surname; 
);

【讨论】:

它像任何其他属性一样工作,但你不能为它设置值(除非你指定一个 setter) 当然不是,也不应该,因为这是一个派生(计算)的属性。如果其他用例需要,可以定义一个 setter。 我不是不同意你的观点^^,只是想澄清一下。 这看起来不错,但我想看看是否有人有更“棱角分明”的解决方案。 有角度的方法是像在那个 plunk 中所做的那样转换响应:jsfiddle.net/roadprophet/YpvG7

以上是关于ngResource 中的虚拟属性的主要内容,如果未能解决你的问题,请参考以下文章

使用 ngResource 在 AngularJS 中设置 enctype

ngResource 将 POST 参数附加到 url

Angularjs ngResource 需要将文件作为字段之一

与 ngResource 相比,使用 Restangular 有啥优势?

AngularJS $resource GET 中的多个参数

AngularJS ngResource 不发送自定义标头