博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Web前端学习笔记——AngularJS之豆瓣电影案例
阅读量:4220 次
发布时间:2019-05-26

本文共 10985 字,大约阅读时间需要 36 分钟。

step-01 构建项目结构

  • 克隆项目骨架

bash $ git clone --depth=1 https://github.com/Micua/angular-boilerplate.git moviecat $ cd moviecat

  • 安装项目依赖

bash $ bower install bootstrap --save

.editorconfig -- 统一不同开发者的不同开发工具的不同开发配置 在Sublime中使用需要安装一个EditorConfig的插件

  • 为NG做一个项目骨架的目的是为了快速开始一个新的项目
  • angular-seed

npm 在 package.json中的script节点中可以定义脚本任务,

API的概念: Application Programxxx Interface 应用程序编程接口

有哪些常见的API

WebAPI 通过WEB方式提供结构叫做 WEBAPI

Math.random() -- api?

所有有输入有输出的事物都可以是API 都是函数

测试WebAPI的工具: POSTMAN

step-02 抽象数据成员,以假数据的方式设计控制器和视图

step-03 图片链接数据绑定BUG

step-04 豆瓣API介绍,加入$http服务对象完成AJAX请求数据

step-05 加载提示,Loading状态设计

step-06 修改字符数组的展示形式

step-07 实现分页功能

step-07 抽象公共的列表页

step-08 搜索功能模块

step-09 详细页模块设计展示

{ "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}}

{<div></div>  {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/

你可能感兴趣的文章
leetcode3. Longest Substring Without Repeating Characters
查看>>
leetcode49. Group Anagrams
查看>>
leetcode136. Single Number
查看>>
leetcode187. Repeated DNA Sequences
查看>>
leetcode166. Fraction to Recurring Decimal
查看>>
leetcode36.Valid Sudoku
查看>>
leetcode85 maximal rectangle
查看>>
2016年半年计划~
查看>>
推荐系统简述(1)基于内容的推荐系统
查看>>
leetcode 149. Max Points on a Line
查看>>
python 小练习之山寨版markdown格式txt文件转html文件
查看>>
python小练习
查看>>
leetcode26. [Array]Remove Duplicates from Sorted Array
查看>>
leetcode 27. [Array]Remove Element
查看>>
leetcode66.[Array] Plus One
查看>>
leetcode283. [Array]Move Zeroes My Submissions Question
查看>>
leetcode292.[Array] Nim Game
查看>>
推荐系统简述(2)基于近邻推荐方法
查看>>
leetcode171.[math] Excel Sheet Column Number
查看>>
决策树知识点整理
查看>>