├── .bowerrc ├── .gitignore ├── LICENSE ├── README.md ├── app.js ├── bin └── www ├── bower.json ├── package.json ├── public ├── application.js ├── example │ ├── controllers │ │ └── example.client.controller.js │ ├── example.client.module.js │ ├── services │ │ └── example.client.service.js │ └── views │ │ └── example.client.view.html ├── stylesheets │ └── style.css └── user │ ├── controllers │ └── user.client.controller.js │ ├── services │ └── user.client.service.js │ ├── user.client.module.js │ └── views │ └── user.client.view.html ├── routes ├── index.js └── users.js └── views ├── error.ejs └── index.ejs /.bowerrc: -------------------------------------------------------------------------------- 1 | { 2 | "directory": "public/lib" 3 | } -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .idea/ 2 | 3 | # Logs 4 | logs 5 | *.log 6 | 7 | # Runtime data 8 | pids 9 | *.pid 10 | *.seed 11 | 12 | # Directory for instrumented libs generated by jscoverage/JSCover 13 | lib-cov 14 | 15 | # Coverage directory used by tools like istanbul 16 | coverage 17 | 18 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 19 | .grunt 20 | 21 | # node-waf configuration 22 | .lock-wscript 23 | 24 | # Compiled binary addons (http://nodejs.org/api/addons.html) 25 | build/Release 26 | 27 | # Dependency directory 28 | # https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git 29 | node_modules 30 | public/lib 31 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 lwdz 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | AngularJS简易入门 2 | ====== 3 | 4 | ## 介绍AngularJS 5 | 6 | * AngularJS是JavaScript前端框架 7 | * 使用MVC架构创建单页应用 8 | 9 | > AngularJS是Google开发的纯客户端JavaScript技术的WEB框架,用于扩展、增强HTML功能,它专为构建强大的WEB应用而设计。 10 | 11 | ## AngularJS的关键概念 12 | 13 | ### AngularJS核心模块 14 | 15 | 包含一些对象和实体,用来完成AngularJS应用的基本操作 16 | 17 | ### angular全局对象 18 | 19 | ```angular``` 全局对象包含一些可以用来创建和启动应用的方法。```angular``` 对象包含了一个精简版的```jQuery``` ,叫做```jqLite``` 。可以使得Angular做一些简单的DOM操作。 20 | 21 | ### AngularJS 模块 22 | 23 | 在AngularJS中,一切都被封装在模块之中。AngularJS需要至少一个模块来进行操作。 24 | 25 | #### 应用模块 26 | 27 | AngularJS需要至少一个模块来启动,这个模块就是应用模块。 28 | 使用```angular.module(name, [requires], [configFn])```来创建和获取模块。 29 | 30 | * ```name```: 模块的名字 31 | * ```requires```: 模块的依赖 32 | * ```configFN```: 模块注册时调用的方法 33 | 34 | 传入一个参数,获取对应模块。传入多个参数进行创建。(类似重载,跟是jQuery的setter,getter类似) 35 | 36 | #### 附加模块 37 | 38 | 同样是AngularJS team开发的,但是不包含在核心功能里的模块。 39 | 40 | #### 第三方模块 41 | 42 | 由其他人开发的模块 43 | 44 | ### 双向数据绑定 45 | 双向数据绑定,使AngularJS应用总是保持model和view的一致。 46 | 47 | > 单向数据绑定与双向数据绑定 48 | 49 | ### 依赖注入 50 | 51 | 示例:使用module的controller方法创建一个controller 52 | 53 | ```javascript 54 | angular.module('someModule').controller('SomeController', 55 | function($scope){ 56 | ... 57 | }); 58 | ``` 59 | 60 | controller方法接收了两个参数,一个是controller的名字,另一个是controller的构造方法。构造方法中被注入了一个AngularJS的对象:$scope。 61 | AngularJS通过方法的参数的名字来进行注入。 62 | 当进行压缩(混淆)的时候,会变成 63 | 64 | ```javascript 65 | angular.module('someModule').controller('SomeController', 66 | function(a){ 67 | ... 68 | }); 69 | ``` 70 | 71 | 这样AngularJS就懵逼了。 72 | 通常采用“注释数组”的方式进行注入 73 | 74 | ```javascript 75 | angular.module('someModule').controller('SomeController', ['$scope', 76 | function($scope) { 77 | ... 78 | }]); 79 | ``` 80 | ###AngularJS指令 81 | AngularJS就是一些标记,一般是属性或者元素名。从根本上讲,AngularJS是通过指令与DOM元素进行交互的。 82 | ####核心指令 83 | AngularJS自带了一些必要的指令。 84 | 最基本的指令:ng-app 一般写在页面的body或者html标签上。 85 | 86 | ```html 87 | 88 | ``` 89 | * ng-controller: 指定哪个contoller来管理这块元素视图 90 | * ng-model: 绑定个哪个值 91 | * ng-show/ng-hide: 根据布尔表达式决定是否显示 92 | * ng-repeat: 迭代数组,重复html元素 93 | 94 | > [查看更多](http://docs.angularjs.org/api/) 95 | 96 | ####自定义指令 97 | 自己写指令,可以根据元素或者属性来修改已有的DOM元素。 98 | 99 | ####启动一个Angluar应用 100 | 启动,或者说引导一个AngularJS应用,就是说告诉Angular在哪个DOM元素是根元素以及何时来初始化Angular应用。 101 | #####自动启动 102 | 使用ng-app指令,当应用的JavaScript文件加载完成时,AngularJS就会找ng-app所在的元素。ng-app可以没有值,也可有一个名字。 103 | 如果有一个名字,则必须创建这个module。 104 | #####手动启动 105 | 需要用到以下方法 106 | 107 | ```javascript 108 | angular. bootstrap(element, [modules], [config]) 109 | ``` 110 | 111 | * element: 想要启动的DOM元素 112 | * modules: 启动的模块 113 | * config: 启动的配置 114 | 115 | 方法在jqLite的document-ready事件中进行调用。 116 | 117 | ##安装AngularJS 118 | 119 | * 使用CDN文件 120 | * 下载后使用自己服务器提供 121 | 122 | ###使用bower管理依赖 123 | ```shell 124 | $ npm install -g bower 125 | ``` 126 | 创建bower.json指定依赖 127 | 128 | ```javascript 129 | { 130 | "name": "MEAN", 131 | "version": "0.0.1", 132 | "dependencies": { } 133 | } 134 | ``` 135 | 136 | ###配置bower依赖管理 137 | 创建.bowerrc文件指定依赖下载的路径 138 | 139 | ```javascript 140 | { 141 | "directory": "public/lib" 142 | } 143 | ``` 144 | ###使用Bower安装AngularJS 145 | ```javascript 146 | { 147 | "name": "MEAN", 148 | "version": "0.0.1", 149 | "dependencies": { 150 | "angular": "~1.2" 151 | } 152 | } 153 | ``` 154 | 155 | ```shell 156 | $ bower install 157 | ``` 158 | 159 | ###配置AngluarJS 160 | 161 | ```html 162 | 163 | 164 | 165 | <%= title %> 166 | 167 | 168 | 169 |

<%= title %>

170 |

Welcome to <%= title %>

171 | 172 | 173 | 174 | ``` 175 | > git checkout -f v1 176 | 177 | ##AngularJS应用结构 178 | 179 | * 水平结构 180 | * 垂直结构 181 | * 垂直结构改良(示例采用此种) 182 | 183 | ##启动(引导)AngularJS应用 184 | 我们采用手动启动的方式。 185 | 比自动启动更加灵活,更加容易控制,然后而并没有什么卵用。 186 | public 目录中创建application.js 187 | 188 | ```javascript 189 | var mainApplicationModuleName = 'mean'; 190 | var mainApplicationModule = angular.module(mainApplicationModuleName, []); 191 | angular.element(document).ready(function() { 192 | angular.bootstrap(document, [mainApplicationModuleName]); 193 | }); 194 | ``` 195 | 在index.ejs中引入application.js 196 | 197 | ```html 198 |
199 | 200 | 201 |
202 | 203 | 204 | ``` 205 | 启动服务,查看效果。(双向数据绑定) 206 | > git checkout -f v3 (忘写v2了) 207 | 208 | ##AngularJS MVC 209 | MVC design pattern 210 | 在public文件中,新建一个名为example的模块文件夹。在example中再建两个子文件夹controllers,views 211 | 在example中新建一个文件example.client.module.js 212 | public/example/example.client.module.js中写入以下代码 213 | 214 | ```javascript 215 | angular.module('example', []); 216 | ``` 217 | 在index.ejs中引入 218 | 219 | ```html 220 | 221 | ``` 222 | 通过依赖注入方式将example模块加入到主应用模块中 223 | 224 | ```javascript 225 | var mainApplicationModule = angular.module(mainApplicationModuleName, ['example']); 226 | ``` 227 | > git checkout -f v4 228 | 229 | ###AngularJS views 230 | example.client.view.html --> public/example/views 231 | 232 | ```html 233 |
234 | 235 | 236 |
237 | ``` 238 | 239 | index.ejs中 240 | 241 | ```html 242 |
243 | ``` 244 | 245 | ###AngularJS controllers and scopes 246 | 247 | * scope是连接controller和view的一个对象 248 | * dom层级的关系,所以scope也是有层级的关系.本scope找不到的对象,会向上去查找。 249 | * 一般使用ng-controller来指定view的controller(也可以在路由配置中指定模controller) 250 | 251 | ```javascript 252 | example.client.controller.js --> public/example/controllers 253 | angular.module('example').controller('ExampleController', ['$scope', 254 | function($scope) { 255 | $scope.name = 'MEAN Application'; 256 | } 257 | ]); 258 | ``` 259 | index.ejs引入 260 | ```html 261 | 262 | ``` 263 | 264 | ```html 265 | example.client.view.html 266 | 267 |
268 | 269 | 270 |
271 | ``` 272 | > git checkout -f v5 273 | 274 | ##AngularJS路由 275 | 276 | AngularJS主要用于“单页应用”,ngRoute管理整个浏览器中的路由。AngularJS将加载定义的模板,把结果写入DOM,服务器只是用来提供静态文件的加载,不对url变化做响应。这样就使的服务器更像一个“面向API”的后端。(好处:移动应用流行,原生应用可以和网页应用共用同一套API) 277 | ###安装ngRoute模块 278 | 279 | ```javascript 280 | { 281 | "name": "MEAN", 282 | "version": "0.0.1", 283 | "dependencies": { 284 | "angular": "~1.2", 285 | "angular-route": "~1.2" 286 | } 287 | } 288 | ``` 289 | ```shell 290 | $ bower install 291 | ``` 292 | index.ejs中引入 293 | 294 | ```html 295 | 296 | ``` 297 | application.js注入 298 | 299 | ```javascript 300 | var mainApplicationModule = angular.module(mainApplicationModuleName, ['ngRoute', 'example']); 301 | ``` 302 | 303 | ###配置􏰔􏰕􏰖 URL 304 | 使用url的hash部分来进行路由,hash部分变化,不向服务器发送请求。(锚点) 305 | (缺点:单页应用不用利于搜索引擎的抓取和SEO。解决:搜索引擎给开发者提供一个标记,来标记应用为单页应用,Hashbangs) 306 | AngluarJS的$locationProvider服务支持这种配置 307 | public/application.js 308 | 309 | ```javascript 310 | mainApplicationModule.config(['$locationProvider', 311 | function($locationProvider) { 312 | $locationProvider.hashPrefix('!'); 313 | } 314 | ]); 315 | ``` 316 | 这样搜索引擎就会等待AJAX的请求,来获得网页内容。 317 | 318 | ###AngluarJS应用路由 319 | 320 | 使用ngRoute中的$routeProvider对象,这个对象提供了一些方法来定义路由行为。在一个模块中注入$routeProvider对象来进行配置。 321 | 322 | ```javascript 323 | example.client.routes.js --> public/example 324 | angular.module('example').config(['$routeProvider', 325 | function($routeProvider) { 326 | $routeProvider.when('/', { 327 | templateUrl: 'example/views/example.client.view.html' 328 | }).otherwise({ 329 | redirectTo: '/' 330 | }); 331 | } 332 | ]); 333 | ``` 334 | 使用angular.module()获得example这个模块,然后使用config方法,注入$routeProvider对象,进行配置。when(),otherwise() 335 | 336 | 除了$routeProvider,另一个打包在ngRoute中的是ng-view,ng-view就是告诉DOM元素,在哪里显示路由视图。 337 | 338 | ```html 339 | app/views/index.ejs 340 |
341 | 342 | 引入 343 | 344 | ``` 345 | > git checkout -f v6 346 | 347 | 348 | ##AngularJS服务 349 | 350 | 单例实体,用于在不同实体中共享信息。可以用来从服务中获取数据,共享缓存数据,注入全局对象等。 351 | 352 | ###AngularJS自带的一些服务 353 | 354 | * $http: 用来处理AJAX请求 355 | 356 | ``` 357 | // Simple GET request example : 358 | $http.get('/someUrl'). 359 | success(function(data, status, headers, config) { 360 | // this callback will be called asynchronously 361 | // when the response is available 362 | }). 363 | error(function(data, status, headers, config) { 364 | // called asynchronously if an error occurs 365 | // or server returns response with an error status. 366 | }); 367 | 368 | // Simple POST request example (passing data) : 369 | $http.post('/someUrl', {msg:'hello word!'}). 370 | success(function(data, status, headers, config) { 371 | // this callback will be called asynchronously 372 | // when the response is available 373 | }). 374 | error(function(data, status, headers, config) { 375 | // called asynchronously if an error occurs 376 | // or server returns response with an error status. 377 | }); 378 | ``` 379 | 380 | * $resource: 用来处理RESTful APIs,支持一系列的方法和参数。 381 | 需要安装angular-resource.js,添加ngResource依赖 382 | 383 | ``` 384 | 默认的动作 385 | { 'get': {method:'GET'}, 386 | 'save': {method:'POST'}, 387 | 'query': {method:'GET', isArray:true}, 388 | 'remove': {method:'DELETE'}, 389 | 'delete': {method:'DELETE'} }; 390 | 也可以加入自定动作 391 | ``` 392 | 393 | * $location: 用来操作url 394 | * $q: 用来操作promises 395 | * $rootScope: 返回rootScope 396 | * $window: 返回浏览器window对象 397 | 398 | ###创建AngluarJS服务 399 | 一般使用两种方法来创建: 400 | 401 | ``` 402 | //使用service提供数据的返回 403 | angular.module('example').factory('ExampleService', [ 404 | function() { 405 | return true; 406 | } 407 | ]); 408 | 409 | //通过service方法实例化一个单例对象,注意使用了prototype的方式 410 | angular.module('example').service('ExampleService', [ 411 | function () { 412 | this.someValue = true; 413 | this.hello = 'world'; 414 | this.firstMethod = function () { 415 | }; 416 | this.secondMethod = function () { 417 | }; 418 | } 419 | ]); 420 | ``` 421 | ###使用服务 422 | 423 | 同样是通过注入的方式 424 | 425 | ``` 426 | 创建services文件夹 --> example.client.service.js文件 427 | ``` 428 | 429 | index.ejs引入 430 | 431 | ``` 432 | 433 | ``` 434 | 435 | example.client.controller.js中注入 436 | 437 | ``` 438 | angular.module('example').controller('ExampleController', ['$scope', 'ExampleService', 439 | function($scope, ExampleService) { 440 | $scope.name = 'MEAN Application'; 441 | $scope.test = ExampleService.hello; 442 | } 443 | ]); 444 | ``` 445 | view中加入显示 446 | 447 | ``` 448 | hello {{test}}!! 449 | ``` 450 | 451 | > git checkout -f v7 452 | > 453 | > git checkout -f v8 增加user模块 454 | > 455 | > git checkout -f v9 user模块使用service与服务器进行交互 456 | -------------------------------------------------------------------------------- /app.js: -------------------------------------------------------------------------------- 1 | var express = require('express'); 2 | var path = require('path'); 3 | var favicon = require('serve-favicon'); 4 | var logger = require('morgan'); 5 | var cookieParser = require('cookie-parser'); 6 | var bodyParser = require('body-parser'); 7 | 8 | var routes = require('./routes/index'); 9 | var users = require('./routes/users'); 10 | 11 | var app = express(); 12 | 13 | // view engine setup 14 | app.set('views', path.join(__dirname, 'views')); 15 | app.set('view engine', 'ejs'); 16 | 17 | // uncomment after placing your favicon in /public 18 | //app.use(favicon(__dirname + '/public/favicon.ico')); 19 | app.use(logger('dev')); 20 | app.use(bodyParser.json()); 21 | app.use(bodyParser.urlencoded({ extended: false })); 22 | app.use(cookieParser()); 23 | app.use(express.static(path.join(__dirname, 'public'))); 24 | 25 | app.use('/', routes); 26 | app.use('/users', users); 27 | 28 | // catch 404 and forward to error handler 29 | app.use(function(req, res, next) { 30 | var err = new Error('Not Found'); 31 | err.status = 404; 32 | next(err); 33 | }); 34 | 35 | // error handlers 36 | 37 | // development error handler 38 | // will print stacktrace 39 | if (app.get('env') === 'development') { 40 | app.use(function(err, req, res, next) { 41 | res.status(err.status || 500); 42 | res.render('error', { 43 | message: err.message, 44 | error: err 45 | }); 46 | }); 47 | } 48 | 49 | // production error handler 50 | // no stacktraces leaked to user 51 | app.use(function(err, req, res, next) { 52 | res.status(err.status || 500); 53 | res.render('error', { 54 | message: err.message, 55 | error: {} 56 | }); 57 | }); 58 | 59 | 60 | module.exports = app; 61 | -------------------------------------------------------------------------------- /bin/www: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | /** 4 | * Module dependencies. 5 | */ 6 | 7 | var app = require('../app'); 8 | var debug = require('debug')('angluar:server'); 9 | var http = require('http'); 10 | 11 | /** 12 | * Get port from environment and store in Express. 13 | */ 14 | 15 | var port = normalizePort(process.env.PORT || '3000'); 16 | app.set('port', port); 17 | 18 | /** 19 | * Create HTTP server. 20 | */ 21 | 22 | var server = http.createServer(app); 23 | 24 | /** 25 | * Listen on provided port, on all network interfaces. 26 | */ 27 | 28 | server.listen(port); 29 | server.on('error', onError); 30 | server.on('listening', onListening); 31 | 32 | /** 33 | * Normalize a port into a number, string, or false. 34 | */ 35 | 36 | function normalizePort(val) { 37 | var port = parseInt(val, 10); 38 | 39 | if (isNaN(port)) { 40 | // named pipe 41 | return val; 42 | } 43 | 44 | if (port >= 0) { 45 | // port number 46 | return port; 47 | } 48 | 49 | return false; 50 | } 51 | 52 | /** 53 | * Event listener for HTTP server "error" event. 54 | */ 55 | 56 | function onError(error) { 57 | if (error.syscall !== 'listen') { 58 | throw error; 59 | } 60 | 61 | var bind = typeof port === 'string' 62 | ? 'Pipe ' + port 63 | : 'Port ' + port; 64 | 65 | // handle specific listen errors with friendly messages 66 | switch (error.code) { 67 | case 'EACCES': 68 | console.error(bind + ' requires elevated privileges'); 69 | process.exit(1); 70 | break; 71 | case 'EADDRINUSE': 72 | console.error(bind + ' is already in use'); 73 | process.exit(1); 74 | break; 75 | default: 76 | throw error; 77 | } 78 | } 79 | 80 | /** 81 | * Event listener for HTTP server "listening" event. 82 | */ 83 | 84 | function onListening() { 85 | var addr = server.address(); 86 | var bind = typeof addr === 'string' 87 | ? 'pipe ' + addr 88 | : 'port ' + addr.port; 89 | debug('Listening on ' + bind); 90 | } 91 | -------------------------------------------------------------------------------- /bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "MEAN", 3 | "version": "0.0.1", 4 | "dependencies": { 5 | "angular": "~1.2", 6 | "angular-route": "~1.2", 7 | "angular-resource": "~1.2" 8 | } 9 | } -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "angluar", 3 | "version": "0.0.0", 4 | "private": true, 5 | "scripts": { 6 | "start": "node ./bin/www" 7 | }, 8 | "dependencies": { 9 | "body-parser": "~1.12.4", 10 | "cookie-parser": "~1.3.5", 11 | "debug": "~2.2.0", 12 | "ejs": "~2.3.1", 13 | "express": "~4.12.4", 14 | "morgan": "~1.5.3", 15 | "serve-favicon": "~2.2.1", 16 | "underscore": "^1.8.3" 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /public/application.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by li on 15/6/3. 3 | */ 4 | var mainApplicationModuleName = 'mean'; 5 | var mainApplicationModule = angular.module(mainApplicationModuleName, ['ngRoute', 'ngResource', 'example', 'user']); 6 | 7 | mainApplicationModule.config(['$locationProvider', 8 | function ($locationProvider) { 9 | $locationProvider.hashPrefix('!'); 10 | } 11 | ]); 12 | 13 | mainApplicationModule.config(['$routeProvider', 14 | function ($routeProvider) { 15 | $routeProvider.when('/', { 16 | templateUrl: 'example/views/example.client.view.html' 17 | }).when('/user', { 18 | templateUrl: 'user/views/user.client.view.html', 19 | controller: 'UserController' 20 | }).otherwise({ 21 | redirectTo: '/' 22 | }); 23 | } 24 | ]); 25 | 26 | angular.element(document).ready(function () { 27 | angular.bootstrap(document, [mainApplicationModuleName]); 28 | }); -------------------------------------------------------------------------------- /public/example/controllers/example.client.controller.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by li on 15/6/3. 3 | */ 4 | angular.module('example').controller('ExampleController', ['$scope', 'ExampleService', 5 | function($scope, ExampleService) { 6 | $scope.name = 'MEAN Application'; 7 | 8 | $scope.test = ExampleService.hello; 9 | } 10 | ]); -------------------------------------------------------------------------------- /public/example/example.client.module.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by li on 15/6/3. 3 | */ 4 | angular.module('example', []); -------------------------------------------------------------------------------- /public/example/services/example.client.service.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by li on 15/6/3. 3 | */ 4 | angular.module('example').service('ExampleService', [ 5 | function () { 6 | this.someValue = true; 7 | this.hello = 'world'; 8 | this.firstMethod = function () { 9 | }; 10 | this.secondMethod = function () { 11 | }; 12 | } 13 | ]); -------------------------------------------------------------------------------- /public/example/views/example.client.view.html: -------------------------------------------------------------------------------- 1 |
2 | 3 | 4 | hello {{test}}!! 5 |
-------------------------------------------------------------------------------- /public/stylesheets/style.css: -------------------------------------------------------------------------------- 1 | body { 2 | padding: 50px; 3 | font: 14px "Lucida Grande", Helvetica, Arial, sans-serif; 4 | } 5 | 6 | a { 7 | color: #00B7FF; 8 | } -------------------------------------------------------------------------------- /public/user/controllers/user.client.controller.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by li on 15/6/4. 3 | */ 4 | angular.module('user').controller('UserController', ['$scope', 'UserService', 5 | function ($scope, UserService) { 6 | $scope.users = UserService.query();//query是$resource的一个默认动作 7 | 8 | $scope.add = function () { 9 | var user = {name: $scope.user.name, age: $scope.user.age}; 10 | UserService.add(user, function (response) { 11 | $scope.users.push(user); 12 | }, function (response) { 13 | alert('fail'); 14 | }); 15 | }; 16 | 17 | //失败之后才和服务器同步,使页面响应更快。(看起来) 18 | $scope.del = function (name, index) { 19 | $scope.users.splice(index, 1) 20 | UserService.remove({name: name}, function (response) { 21 | 22 | }, function (response) { 23 | $scope.users = UserService.query(); 24 | }); 25 | }; 26 | 27 | //添加完成之后重新获取,可以使页面中和服务器保持一致。 28 | $scope.update = function () { 29 | UserService.update({name: 'li', age: 16}, function (response) { 30 | $scope.users = UserService.query(); 31 | }, function (response) { 32 | alert('fail'); 33 | }); 34 | } 35 | 36 | } 37 | ]); -------------------------------------------------------------------------------- /public/user/services/user.client.service.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by li on 15/6/4. 3 | */ 4 | angular.module('user').factory('UserService', ['$resource', 5 | function ($resource) { 6 | return $resource('/users/:name', {name: '@name'}, { 7 | update: {method: 'PUT'}, 8 | add: {method: 'POST', params: {name: ''}} 9 | }); 10 | } 11 | ]); -------------------------------------------------------------------------------- /public/user/user.client.module.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by li on 15/6/4. 3 | */ 4 | angular.module('user', []); -------------------------------------------------------------------------------- /public/user/views/user.client.view.html: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /routes/index.js: -------------------------------------------------------------------------------- 1 | var express = require('express'); 2 | var router = express.Router(); 3 | 4 | /* GET home page. */ 5 | router.get('/', function(req, res, next) { 6 | res.render('index', { title: 'Angular' }); 7 | }); 8 | 9 | module.exports = router; 10 | -------------------------------------------------------------------------------- /routes/users.js: -------------------------------------------------------------------------------- 1 | var express = require('express'); 2 | var router = express.Router(); 3 | var _ = require('underscore'); 4 | 5 | var users = [ 6 | {name: 'li', age: 18}, 7 | {name: 'wang', age: 38}, 8 | {name: 'liu', age: 27} 9 | ]; 10 | 11 | router.get('/', function (req, res, next) { 12 | res.json(users); 13 | }); 14 | 15 | router.post('/', function (req, res, next) { 16 | var user = req.body; 17 | users.push(user); 18 | res.send(user); 19 | }); 20 | 21 | router.put('/:userId', function (req, res, next) { 22 | 23 | var name = req.params.userId; 24 | var age = req.body.age; 25 | 26 | _.each(users, function (e) { 27 | if (e.name === name) { 28 | e.age = age; 29 | } 30 | }); 31 | 32 | res.end(); 33 | }); 34 | 35 | router.delete('/:userId', function (req, res, next) { 36 | 37 | var name = req.params.userId; 38 | 39 | users = _.reject(users, function (e) { 40 | return e.name === name; 41 | }); 42 | 43 | res.end(); 44 | }); 45 | module.exports = router; 46 | -------------------------------------------------------------------------------- /views/error.ejs: -------------------------------------------------------------------------------- 1 |

<%= message %>

2 |

<%= error.status %>

3 |
<%= error.stack %>
4 | -------------------------------------------------------------------------------- /views/index.ejs: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | <%= title %> 5 | 6 | 7 | 8 |

<%= title %>

9 |

Welcome to <%= title %>

10 |
11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | --------------------------------------------------------------------------------