AngularJS订阅API服务
本篇使用AngularJS实现订阅某个API服务。
首页大致是:
其中,what's on显示首页内容,Search通过输入关键词调用API服务显示到页面,MyShows显示订阅的内容。
Sarch页界面如下:
通过在搜索框中输入关键词,把查询到信息显示在当前页面,并且可以点击订阅和取消订阅按钮。
My Shows页界面如下:
显示订阅的内容,并且提供取消订阅按钮。
首先,需要了解API提供方所要求的格式。大致是:http://api.themoviedb.org/3/search/tv?api_key=87de9079e74c828116acce677f6f255b&query=Star%20Trek
文件结构:
node_modules/ [通过node下载的module存放于此]
sections/
.....my-shows/
..........my-shows.ctrl.js
..........my-shows.tpl.html
.....search/
..........search.css
..........search.ctrl.js
..........search.tpl.html
.....show/
..........show.ctrl.js
..........show.tpl.html
.....whats-on/
..........whats-on.ctrl.js
..........whats-on.tpl.html
services/
.....show.fct.js [search页需要的查询服务封装在这里]
.....store.fct.js [search需要的操作服务封装在这里]
app.core.js
app.js
app.routes.js [设置路由]
app.services.js
index.html
各个module之间的关系是重中之重,如下:
通过node需要安装的module命令如下:
npm install bootstrap
npm install angular
npm install angular-route
npm install angular-animate
npm i angular-local-storage
index.html
<a href="#/">What's on</a> <a href="#/my-shows">My Shows</a> <a href="#/search">Search</a> <main ng-view=""></main> <!--js引用--> angular.min.js angular-route.min.js angular-animate.min.js angular-local-storage.min.js ui-bootstrap-tpls-0.12.1.min.js app.js app.core.js app.routes.js app.services.js <!--SERVICES--> show.fct.js store.fct.js <!--CONTROLLERS--> my-shows.ctrl.js search.ctrl.js show.ctrl.js whats-on.ctrl.js
app.routes.js
在这里设置路由。
angular.module('app.routes',['ngRoute']) .config(routes); function routes($routeProvider){ $routeProvider .when('/',{ templateUrl: 'sections/whats-on/whats-on.tpl.html', controller:'WhatsOnController', controllerAs: 'whatsOn' }) .when('/my-shows',{ templateUrl: 'sections/my-shows/my-shows.tpl.html', controller: 'MyShowsController', controllerAs: 'myShows' }) .when('/search',{ templateUrl: 'sections/search/search.tpl.html', controller: 'SearchController', controllerAs: 'search' }) .when('/show/:id',{ templateUrl: 'sections/show/show.tpl.html', controller: 'ShowController', controllerAs: 'show' }) .otherwise({ redirectTo: '/' }); }
show.fct.js
在这里,通过factory的方式返回一个对象,该对象包含查询的方法。
angular .module('app.services') .constant('API_KEY', '87de9079e74c828116acce677f6f255b') .constant('BASE_URL', 'http://api.themoviedb.org/3') .factory('ShowService', dataService); function dataService($http, API_KEY, BASE_URL, $log) { var data = { 'get': get, //使用的时候不带参数 'search': search }; //经$http返回的是一个promise function makeRequest(url, params) { var requestUrl = BASE_URL + '/' + url + '?api_key=' + API_KEY; //遍历查询参数 angular.forEach(params, function (value, key) { requestUrl = requestUrl + '&' + key + '=' + value; }); //发出请求 //$http接受一个对象也是第一次见 return $http({ 'url': requestUrl, 'method': 'GET', 'headers': { 'Content-Type': 'application/json' }, 'cache': true }).then(function (response) { return response.data; }).catch(dataServiceError);//旦凡一个函数作为令一个函数的实参,这两个函数的参赛也进行了传递 } //定义的时候带参数 function get(id) { return makeRequest('tv/' + id, {}); } //查询 function search(query){ return makeRequest("search/tv",{query:query}).then(function(data){ return data.results; }); } function dataServiceError(errorResponse) { $log.error('XHR Failed for ShowService'); $log.error(errorResponse); return errorResponse; } //factory返回的就是一个对象 return data; }
以上,在makeRequest方法中,不仅可以对url进行拼接,还对查询字符串(以对象的形式)进行了拼接。发出请求返回的是promise,即在调用的时候还可以使用then方法。
store.fct.js
这里封装了订阅和取消订阅的操作。
angular .module('app.services') .factory('StoreFactory', dataService); function dataService(localStorageService){ var _shows = []; var ls = localStorageService.get('store'); if(ls !== null){ _shows = ls; } var service = { 'addShow':addShow, 'getShow':getShow, 'getShows':getShows, 'removeShow':removeShow }; //订阅 function addShow(data){ _shows.push(data); save(); } function getShow(id){ var result=false; angular.forEach(_shows, function(show){ if(result===false){ if(show.id===id){ result = show; } } }); return result; } function getShows(){ return _shows; } //取消订阅 function removeShow(id){ var idx=-1; var found=false; angular.forEach(_shows, function(show){ if(found === false){ if(show.id === id){ found=true; } idx++; } }); if(found === true){ _shows.splice(idx, 1); save(); } } //保存到本地 function save(){ localStorageService.set('store',_shows); } return service; }
所以,所谓的订阅就是把获取到的数据保存在某个地方,取消订阅就是把数据从某个地方删除。
search.ctrl.js
angular.module('app.core').controller('SearchController', function (ShowService, $timeout, StoreFactory) { var vm = this; vm.results = false; vm.searching = false; vm.query = function (query) { vm.searching = true; ShowService.search(query).then(function (response) { vm.results = response; $timeout(function(){ vm.searching = false; },500); }).catch(function (error) { }); }; //订阅 vm.trackShow=function(show){ StoreFactory.addShow(show); } //取消订阅 vm.unTrackShow = function(id){ StoreFactory.removeShow(id); } //根据id搜索本地的store,存在就返回true, 不存在就返回false vm.hasShow = function(id){ return (StoreFactory.getShow(id) !== false); } });
search.tpl.html
<input type="text" name="query" ng-model="query"/> <p ng-show="search.searching">Perfoming search...</p> <button ng-click="search.query(query)">Search</button> <ul> <li ng-repeat="show in search.results track by show.id"> ... <div ng-switch="search.hasShow(show.id)"> ... <button ng-switch-when="false" ng-click="search.trackShow(show)">Track Show</button> <button ng-switch-when="true" ng-click="search.unTrackShow(show.id)">UnTrack Show</button> </div> </li> <li class="no-data" ng-if="search.results === false">Find shows to track by using the search bar above.</li> <li class="no-data" ng-if="search.results.length == 0">Your search did not return any results, try again.</li> </ul>
以上,本地存在就显示UnTrack Show按钮,本地不存在就显示Track Show按钮。