本文共 10985 字,大约阅读时间需要 36 分钟。
bash $ git clone --depth=1 https://github.com/Micua/angular-boilerplate.git moviecat $ cd moviecat
bash $ bower install bootstrap --save
.editorconfig -- 统一不同开发者的不同开发工具的不同开发配置 在Sublime中使用需要安装一个EditorConfig的插件
npm 在 package.json中的script节点中可以定义脚本任务,
API的概念: Application Programxxx Interface 应用程序编程接口
有哪些常见的API
WebAPI 通过WEB方式提供结构叫做 WEBAPI
Math.random() -- api?
所有有输入有输出的事物都可以是API 都是函数
测试WebAPI的工具: POSTMAN
{ "name": "angular-boilerplate", "version": "1.0.0", "description": "iceStone angular boilerplate", "scripts": { "postinstall": "bower install", "prestart": "npm install", "start": "./node_modules/.bin/hs -a localhost -p 9000 -o", "pretest": "npm install", "test": "./node_modules/.bin/browser-sync start --server app --files 'app/index.html' --no-notify" }, "keywords": [ "iceStone", "Micua", "Angular", "Boilerplate" ], "author": "iceStone(http://wedn.net/)", "license": "ISC", "dependencies": {}, "devDependencies": { "browser-sync": "^2.11.1", "http-server": "^0.8.5" }}
豆瓣电影
'use strict';// Declare app level module which depends on views, and componentsangular.module('moviecat', [ 'ngRoute', 'moviecat.movie_detail', 'moviecat.movie_list', 'moviecat.directives.auto_focus', ]) // 为模块定义一些常量 .constant('AppConfig', { pageSize: 10, listApiAddress: 'http://api.douban.com/v2/movie/', detailApiAddress: 'http://api.douban.com/v2/movie/subject/' }) .config(['$routeProvider', function($routeProvider) { $routeProvider.otherwise({ redirectTo: '/in_theaters/1' }); }]) .controller('SearchController', [ '$scope', '$route', 'AppConfig', function($scope, $route, AppConfig) { $scope.input = ''; // 取文本框中的输入 $scope.search = function() { // console.log($scope.input); $route.updateParams({ category: 'search', q: $scope.input }); }; } ]);// .controller('NavController', [// '$scope',// '$location',// function($scope, $location) {// $scope.$location = $location;// $scope.$watch('$location.path()', function(now) {// if (now.startsWith('/in_theaters')) {// $scope.type = 'in_theaters';// } else if (now.startsWith('/coming_soon')) {// $scope.type = 'coming_soon';// } else if (now.startsWith('/top250')) {// $scope.type = 'top250';// }// console.log($scope.type);// });// }// ])
/* * Base structure *//* Move down content because we have a fixed navbar that is 50px tall */body { padding-top: 50px;}/* * Global add-ons */.sub-header { padding-bottom: 10px; border-bottom: 1px solid #eee;}/* * Top navigation * Hide default border to remove 1px line. */.navbar-fixed-top { border: 0;}/* * Sidebar *//* Hide for mobile, show later */.sidebar { display: none;}@media (min-width: 768px) { .sidebar { position: fixed; top: 51px; bottom: 0; left: 0; z-index: 1000; display: block; padding: 20px; overflow-x: hidden; overflow-y: auto; /* Scrollable contents if viewport is shorter than content. */ background-color: #f5f5f5; border-right: 1px solid #eee; }}/* Sidebar navigation */.nav-sidebar { margin-right: -21px; /* 20px padding + 1px border */ margin-bottom: 20px; margin-left: -20px;}.nav-sidebar > li > a { padding-right: 20px; padding-left: 20px;}.nav-sidebar > .active > a,.nav-sidebar > .active > a:hover,.nav-sidebar > .active > a:focus { color: #fff; background-color: #428bca;}/* * Main content */.main { padding: 20px;}@media (min-width: 768px) { .main { padding-right: 40px; padding-left: 40px; }}.main .page-header { margin-top: 0;}/* * Placeholder dashboard ideas */.placeholders { margin-bottom: 30px; text-align: center;}.placeholders h4 { margin-bottom: 0;}.placeholder { margin-bottom: 20px;}.placeholder img { display: inline-block; border-radius: 50%;}.list-group .media { margin-top: 0;}.spinner { margin: 100px auto; width: 40px; height: 40px; position: relative; text-align: center; -webkit-animation: sk-rotate 2.0s infinite linear; animation: sk-rotate 2.0s infinite linear;}.dot1,.dot2 { width: 60%; height: 60%; display: inline-block; position: absolute; top: 0; background-color: #333; border-radius: 100%; -webkit-animation: sk-bounce 2.0s infinite ease-in-out; animation: sk-bounce 2.0s infinite ease-in-out;}.dot2 { top: auto; bottom: 0; -webkit-animation-delay: -1.0s; animation-delay: -1.0s;}@-webkit-keyframes sk-rotate { 100% { -webkit-transform: rotate(360deg) }}@keyframes sk-rotate { 100% { transform: rotate(360deg); -webkit-transform: rotate(360deg) }}@-webkit-keyframes sk-bounce { 0%, 100% { -webkit-transform: scale(0.0) } 50% { -webkit-transform: scale(1.0) }}@keyframes sk-bounce { 0%, 100% { transform: scale(0.0); -webkit-transform: scale(0.0); } 50% { transform: scale(1.0); -webkit-transform: scale(1.0); }}.mask { position: fixed; left: 0; top: 0; right: 0; bottom: 0; background-color: rgba(0, 0, 0, .4); z-index: 2000;}.pager a{ cursor: pointer;}
{ {title}}
{ {message}}
总共:{
{totalCount}}条记录,第{ {currentPage}}/{ {totalPages}}页
(function(angular) { 'use strict'; // 创建正在热映模块 var module = angular.module( 'moviecat.movie_list', [ 'ngRoute', 'moviecat.services.http' ]); // 配置模块的路由 module.config(['$routeProvider', function($routeProvider) { $routeProvider.when('/:category/:page', { templateUrl: 'movie_list/view.html', controller: 'MovieListController' }); }]); module.controller('MovieListController', [ '$scope', '$route', '$routeParams', 'HttpService', 'AppConfig', function($scope, $route, $routeParams, HttpService, AppConfig) { var count = AppConfig.pageSize; // 每一页的条数 var page = parseInt($routeParams.page); // 当前第几页 var start = (page - 1) * count; // 当前页从哪开始 // 控制器 分为两步: 1. 设计暴露数据,2. 设计暴露的行为 $scope.loading = true; // 开始加载 $scope.subjects = []; $scope.title = 'Loading...'; $scope.message = ''; $scope.totalCount = 0; $scope.totalPages = 0; $scope.currentPage = page; HttpService.jsonp( AppConfig.listApiAddress + $routeParams.category, // $routeParams 的数据来源:1.路由匹配出来的,2.?参数 { start: start, count: count, q: $routeParams.q }, function(data) { $scope.title = data.title; $scope.subjects = data.subjects; $scope.totalCount = data.total; $scope.totalPages = Math.ceil($scope.totalCount / count); $scope.loading = false; $scope.$apply(); // $apply的作用就是让指定的表达式重新同步 }); // 暴露一个上一页下一页的行为 $scope.go = function(page) { // 传过来的是第几页我就跳第几页 // 一定要做一个合法范围校验 if (page >= 1 && page <= $scope.totalPages) $route.updateParams({ page: page }); }; } ]);})(angular);// var doubanApiAddress = 'http://api.douban.com/v2/movie/in_theaters';// // 测试$http服务// // 在Angular中使用JSONP的方式做跨域请求,// // 就必须给当前地址加上一个参数 callback=JSON_CALLBACK// $http.jsonp(doubanApiAddress+'?callback=JSON_CALLBACK').then(function(res) {// // 此处代码是在异步请求完成过后才执行(需要等一段时间)// if (res.status == 200) {// $scope.subjects = res.data.subjects;// } else {// $scope.message = '获取数据错误,错误信息:' + res.statusText;// }// }, function(err) {// console.log(err);// $scope.message = '获取数据错误,错误信息:' + err.statusText;// });
{ {movie.title}}
{
{movie.summary}}
(function(angular) { 'use strict'; // 创建正在热映模块 var module = angular.module( 'moviecat.movie_detail', [ 'ngRoute', 'moviecat.services.http' ]); // 配置模块的路由 module.config(['$routeProvider', function($routeProvider) { $routeProvider.when('/detail/:id', { templateUrl: 'movie_detail/view.html', controller: 'MovieDetailController' }); }]); module.controller('MovieDetailController', [ '$scope', '$route', '$routeParams', 'HttpService', 'AppConfig', function($scope, $route, $routeParams, HttpService, AppConfig) { $scope.movie = {}; $scope.loading = true; var id = $routeParams.id; var apiAddress = AppConfig.detailApiAddress + id; // 跨域的方式 HttpService.jsonp(apiAddress, {}, function(data) { $scope.movie = data; $scope.loading = false; $scope.$apply(); }); } ]);})(angular);
(function(angular) { angular.module('moviecat.directives.auto_focus', []) .directive('autoFocus', ['$location', function($location) { // Runs during compile // var path = $location.path(); // /coming_soon/1 // console.log(path); return { restrict: 'A', // E = Element, A = Attribute, C = Class, M = Comment link: function($scope, iElm, iAttrs, controller) { $scope.$location = $location; $scope.$watch('$location.path()', function(now) { // 当path发生变化时执行,now是变化后的值 var aLink = iElm.children().attr('href'); var type = aLink.replace(/#(\/.+?)\/\d+/, '$1'); // /coming_soon if (now.startsWith(type)) { // 访问的是当前链接 iElm.parent().children().removeClass('active'); iElm.addClass('active'); } }) // iElm.on('click', function() { // iElm.parent().children().removeClass('active'); // iElm.addClass('active'); // }); } }; }]);})(angular);
'use strict';(function(angular) { // 由于默认angular提供的异步请求对象不支持自定义回调函数名 // angular随机分配的回调函数名称不被豆瓣支持 var http = angular.module('moviecat.services.http', []); http.service('HttpService', ['$window', '$document', function($window, $document) { // url : http://api.douban.com/vsdfsdf ->
转载地址:http://inxmi.baihongyu.com/