angular学习笔记(二十八-附1)-$resource中的资源的方法
通过$resource获取到的资源,或者是通过$resource实例化的资源,资源本身就拥有了一些方法,$save,$delete,$remove,可以直接调用来保存该资源:
比如有一个$resource创建的服务:
var service = angular.module('myRecipe.service',['ngResource']); service.factory('Recipe',['$resource',function($resource){ return $resource('/recipe/:id',{id:'@id'}); }]); service.factory('loadRecipes',['Recipe','$q',function(Recipe,$q){ return function(){ var defer = $q.defer(); Recipe.query(function(recipes){ defer.resolve(recipes) },function(err){ defer.reject(err) }); return defer.promise } }]); service.factory('loadRecipe',['Recipe','$q','$route','$routeParams',function(Recipe,$q,$route,$routeParams){ return function(){ var defer = $q.defer(); Recipe.get({id:$route.current.params.recipeId},function(recipe){ defer.resolve(recipe) },function(err){ defer.reject(err) }); return defer.promise } }]);
然后我通过loadRecipe方法获取到了一个recipe,修改了recipe后需要对它进行提交保存,以下两种方式是一样的:
1. 通过$resource的save方法(第一个参数是请求提,第二个参数是请求完成后的回调)
Recipe.save($scope.recipe,function(){ $location.path('/view/'+$scope.recipe.id) });
2. 由于recipe本身就是通过$resource获取的资源,所以它拥有$save方法,$save方法里的函数就是保存成功后的回调.
$scope.recipe.$save(function(){ $location.path('/view/'+$scope.recipe.id) });
除了通过loadRecipe获取到的资源,通过$resource实例化的资源也有$save方法:
比如下面的recipe:
$scope.recipe = new Recipe({ ingredients:[{}] }); $scope.save = function(invalid){ if(invalid){ return false } Recipe.save($scope.recipe,function(recipe){ $location.path('/view/'+recipe.id) }); };
$resource()中第二个参数{id:'@id'},表示url中的:id 将会使用资源的id属性值,也就是recipe的id属性值.
还可以通过$resource()第三个参数来给资源自定义方法:
return $resource('/card/user/:userID/:id',{userID:123,id:'@id'},{charge:{method:'POST',params:{charge:true},isArray:false}})
来分析一下这里的第三个参数 {charge:{method:'POST',params:{charge:true},isArray:false}}
1.charge是自定义方法的名字,资源就可以通过$charge()来调用该自定义方法
2.charge属性值是一个json对象,里面有三个属性:
method: 该方法的请求方式: 'POST','GET','DELETE','PUT',等,这里的请求方式可以自定义方法,$resource()返回的对象的get,query,save,remove,delete里用到的只有'GET','POST','DELETE'三种请求方式,但是这里自定义的方法,可以使用$http的所以请求方式. 所以,如果要自定义请求方式,也是通过自定义方法来创建的.
params: 定义请求url后面的参数,这里是{charge:true},就会向url?charge=true发送请求
isArray: 定义返回的数据的格式是否是数组
3.charge属性值除了2里说到的三个属性,还有所有$http里所有可配置的项:
headers:,
transformRequest:,
transformResponse:,
cache:,
timeout:,
withCredentials:
这些项的意思和具体怎么配置,请参考之前将$http的文章,他们是一致的.
eg:
HttpREST.factory('cardResource',function($resource){ return $resource('/card/user/:userID/:id',{userID:123,id:'@id'},{charge:{method:'POST',params:{charge:true},isArray:false}}) }); HttpREST.factory('httpCard',function($q,cardResource){ return { getById:function(cardID){ var defer = $q.defer(); cardResource.get({id:cardID},function(data,headers){ defer.resolve(data); },function(data,headers){ defer.reject(data); }); return defer.promise } } }); $scope.addCharge = function(){ $scope.card_1.then(function(card){ card.$charge({amount:100}); }) }
注意,card_1得到的是promise对象,而不是资源本身,要获得实际的资源,要通过它的then方法里的函数的参数来获得.关于这个问题,请查看:
http://www.cnblogs.com/liulangmao/p/3907307.html
$charge里的参数表示url后面的参数,也就是说:
card.$charge({amount:100}) 向/card/user/123/1?charge=turn&amount=100发送了post请求,请求体就是card
请求url里的1是因为在$resource()第二个参数中配置了{id:@id},所以就是card的id,
请求参数是charge=true是因为在$resource()第三个参数中配置了{charge:{params:{charge:true}}
请求方式是post是因为在$resource()第三个参数中配置了{charge:{method:'POST',params:{charge:true}}}
请求参数是amount=100是因为在调用card.$charge()的时候传入了参数{amount:100}
资源的方法还有一个特性: 在请求完成后,会自动用返回值来填充调用方法的资源,继而更新视图.无需在回调手动处理:
eg:
html:
<button ng-click="addCharge()">给建设银行的卡充值100元</button> <br/> <span>{{card_1['name']}}</span> <span>{{card_1['amount']}}</span> <br/>
js:
$scope.addCharge = function(){ $scope.card_1.then(function(card){ card.$charge({amount:100}); }) }
node:
app.post('/card/user/123/:id',function(req,res){ var index = req.params.id ? req.params.id-1 : cards.length; var query = url.parse(req.url,true)['query']; if (query.charge){ cards[index]['amount']+= Number(query['amount']) } else { cards[index] = req.body; } res.send(cards[index]); });
点击充值后,后台会给建设银行卡添加100元,然后再把建设银行卡这个资源返回给客户端:
点击按钮后:
我们可以看到,在card.$charge({amount:100})这个调用中,我们并没有书写回调来改变$scope.card_1,但是视图里card_1['amount']确实发生了变化,原因是,
angular自动将返回值填充了card,而card是card_1的$$v属性值(关于$$v请查看http://www.cnblogs.com/liulangmao/p/3907307.html),所以视图里的card_1也会被更新.