【问题标题】:What is the difference between Class actions and Instance actions in AngularJs?AngularJs 中的类动作和实例动作有什么区别?
【发布时间】:2014-06-09 08:00:22
【问题描述】:

From the docs:

类操作返回空实例(具有附加属性 以下)。实例动作返回动作的承诺

但是,文档并没有明确区分类操作和实例操作。如果可能的话,您能否举一个很好的例子指出不同之处?

【问题讨论】:

    标签: angularjs angularjs-service angularjs-resource


    【解决方案1】:

    当您创建一个新的资源类型时,您向它提供了一个可以执行的操作列表。默认情况下,这些是getsavequerydeleteremove(我认为删除只是删除的别名)。您可以添加自己的,如文档中所述。

    类与实例的区别在于它为方便使用所做的事情。 “类操作”是指从您自己创建的资源类中调用操作,有点像其他语言中的静态或共享方法。当您还没有实例时,这可用作获取、查询或保存资源实例的入口点。 getquery 是最明显的例子。如果你有一个Car 资源,并且你需要检索它,你从哪里开始?当然是集体诉讼,例如get

    现在,当您的资源类检索现有实例或创建新实例时,$resource 将使用为您的资源定义的操作扩展您的实例,但在它们前面加上 $,这样它们就不会发生冲突与您的资源上的字段。这些是您的实例操作。实例和类之间的区别在于,实例是在当前实例的上下文中完成的。因此,如果您get 一个实例,然后在该实例上调用$save$delete,它将专门保存或删除该实例。实例操作只是为了方便。

    所以它们几乎相同,不同之处在于它们被使用的上下文。

    function($resource) {     
    
       // first let's define a new resource for car, where all cars have an id field
       // calling $resource will create a new resource class that can be used to 
       // create, retrieve, update, or delete instances
       // this is usually done as a service and injected into controllers as needed.
       var Car = $resource('/api/car/:id', {id: '@id'});
    
       // the car class we just created has some class actions that can help you query for or get car instances
       // let's create a new instance of a car and save it
       var newCar = new Car({make: 'Toyota', model: 'Prius'});
       // the prototype of Car includes the instance action versions of the actions defined for the resource. below, $save is your instance action
       newCar.$save(); // server will respond with the object after it's saved, so we can now access the id. let's say the id it returned is 24, we'll reference this value later.
    
    
       // now, let's imagine some time later we want to retrieve the car and update it
       // Car.get is a class action that requests the resource from the server, parses the JSON into an object, and merges it with the Car instance prototype so you have your instance actions
       // let's get the car we created previously.
       // remember, this is done asynchronously, so we will do our work in a success handler that we provide to get
       Car.get({id: 24}, function(myCar) {
           // let's update the car now that we have it. let's set the year of the model and the color
           myCar.year = 2004;
           myCar.color = 'white';
    
           // now, let's save our changes by calling the instance action $save
           myCar.$save();
       });
    
    
       // now, let's query for all cars and get an array back
       // query is a class function that expects an array of your resource to be returned
       Car.query(function(cars) {
            // trivial example, we're just going to enumerate the cars we found and log some info about them
           for(var i = 0; i < cars.length; i++)
              console.log('Found ' + cars[0].color + ' ' cars[0].year + ' ' + cars[0].make + ' ' + cars[0].model);
       });
    
    
       // ok, let's delete the car we created earlier. use the class action delete
       Car.delete({id: 24});
    }
    

    从技术上讲,您可以将任何动作称为类或实例,但很明显有些动作很难用作实例动作,反之亦然。例如,虽然您在技术上可以使用 query 作为实例操作,但实际上您不会这样做,因为这是额外的工作而且很尴尬(您必须这样做 new Car().$query()。这很愚蠢。Car.query() 更容易并且更有意义)。所以,我上面例子中的用法代表了你的正常用法。


    更新:

    save$save

    $savesave 类似,但它假定您要在保存期间提交的数据是它本身,因为$save 是一个实例操作。它特别有用,因为在收到响应后,它会使用 HTTP 端点返回的对象进行自我更新。因此,如果您的服务使用在服务器端填充的一些附加值(例如 ID)保存对象,然后将对象作为 JSON 发送回,$save 将使用返回的 JSON 对象更新实例。

     var car = new Car({make: 'Toyota', model: 'Prius'});
     // at this point there is no id property, only make and model
     car.$save(function() {
        // angular is async, so we need a success handler to continue the explanation
    
        // assuming your server assigned an ID and sent the resulting object back as JSON, you can now access id off the original object
        console.log(car.id); // has a value now
     });
    

    你可以用类方法做一些类似的事情,但这很尴尬,尤其是当你的控制器中的其他代码需要在你处理汽车时引用它时

     Car.save({make: 'Toyota', model: 'Prius'}, function(car) {
           // ok, we have an ID now
           console.log(car.id);
     });
    

     var car = new Car({...});
     Car.save(car, function(newCar) {
          car = newCar; // wut? that's awkward
     });
    

    save 可能在您快速保存小对象或执行某种“即发即弃”的情况下很有用。反正我自己很少用save

    【讨论】:

    • 感谢您的精彩解释。就一件事。 “保存”是默认操作。它与 $save 有何不同?是否有任何实际情况应该使用“save”而不是 $save。我在互联网上没有看到任何人使用默认操作“保存”的示例。
    • 请记住(如果我说得不够清楚,很抱歉),save$save(分别是类与实例)几乎相同,除了 $save 是在该实例是Car.save() 的一种快捷方式,因为在保存时,$resource 将使用从 http 端点返回的值更新实例(这是在我上面的示例中保存后设置 ID 的方式)。你很少看到有人使用.save,因为与创建实例和调用.$save相比,它并不是很有用。
    • 再次感谢。 Cars.length 似乎仅在 isArray 为真时才有效。远程服务器未返回数组 (isArray: false)。我还能统计服务器返回的对象吗?
    • 如果您的查询 URL 没有返回对象数组,您可以使用拦截器在返回实际数组之前修复响应。对于包含总计数和一页项目的响应,我已经这样做了。
    猜你喜欢
    • 1970-01-01
    • 2019-10-26
    • 2016-03-17
    • 1970-01-01
    • 2015-09-10
    • 2019-10-18
    • 2012-07-28
    • 1970-01-01
    相关资源
    最近更新 更多