1.新建项目
2.新建Model
public class TodoItem { public int Id { get; set; } public string Key { get; set; } public string Name { get; set; } public bool IsComplete { get; set; } public string Desc { get; set; } }
3.数据访问接口
public interface ITodoRepository { IEnumerable<TodoItem> GetAll(); void Add(TodoItem item); TodoItem Find(string key); TodoItem Remove(string key); void Update(TodoItem item); }
4.接口实现
public class TodoRepository : ITodoRepository { //fake datasource static ConcurrentDictionary<string, TodoItem> _todos = new ConcurrentDictionary<string, TodoItem>(); //constructor public TodoRepository() { TodoItem item = new TodoItem() { Id=1, Key = Guid.NewGuid().ToString(), Name = "first todo item", IsComplete = false, Desc="desc content from first todo" }; _todos.TryAdd(item.Key, item); } //get all items public IEnumerable<TodoItem> GetAll() { return _todos.Values; } //add new item public void Add(TodoItem item) { item.Id = 1; item.Key = Guid.NewGuid().ToString(); item.Name = Guid.NewGuid().ToString().Split('-')[0].ToUpper(); _todos[item.Key] = item; } //find the item by key public TodoItem Find(string key) { TodoItem item; _todos.TryGetValue(key, out item); return item; } //remove the item by key public TodoItem Remove(string key) { TodoItem item; _todos.TryGetValue(key, out item); _todos.TryRemove(key, out item); return item; } //update the item by key public void Update(TodoItem item) { _todos[item.Key] = item; } }
5.api
using System.Collections.Generic; using Microsoft.AspNetCore.Mvc; using ToDoApi.Models; namespace ToDoApi.Controllers { [Route("api/[controller]")] public class TodoController:Controller { public ITodoRepository _TodoRepository { get; set; } public TodoController(ITodoRepository todoRepository) { _TodoRepository = todoRepository; } //get:api/todo public IEnumerable<TodoItem> GetAll() { return _TodoRepository.GetAll(); } //get:api/todo/id [HttpGet("{id}", Name = "GetTodo")] public IActionResult GetById(string id) { var item = _TodoRepository.Find(id); if (item == null) { return NotFound(); } return new ObjectResult(item); } //put: api/todo [HttpPost] //[HostAuthentication(DefaultAuthenticationTypes.ExternalBearer)] public IActionResult Create(TodoItem item) { if (item == null) { return BadRequest(); } _TodoRepository.Add(item); return CreatedAtRoute("GetTodo", new { controller = "Todo", id = item.Key }, item); } //Update [HttpPut("{id}")] public IActionResult Update(string id, [FromBody] TodoItem item) { if (item == null || item.Key != id) { return BadRequest(); } var todo = _TodoRepository.Find(id); if (todo == null) { return NotFound(); } _TodoRepository.Update(item); return new NoContentResult(); } //delete:api/todo/id [HttpDelete("{id}")] public void Delete(string id) { _TodoRepository.Remove(id); } } }
6.Gulp文件
var gulp = require('gulp'), path = require("path"), livereload = require('gulp-livereload'), connect = require('gulp-connect'), open = require('open'), watch=require('gulp-watch'), port=9000; var PATHS = { src: 'app/**/*.ts', typings: 'node_modules/angular2/bundles/typings/**/*.d.ts', libs: [ "node_modules/angular2/bundles/angular2.dev.js", "node_modules/angular2/bundles/angular2-polyfills.js", "node_modules/angular2/bundles/router.dev.js", "node_modules/angular2/bundles/http.dev.js", "node_modules/systemjs/dist/system.src.js", "node_modules/rxjs/bundles/Rx.js" ], html: 'app/**/*.html', dist: "dist" }; gulp.task('clean', function (done) { var del = require('del'); del(['dist'], done); }); gulp.task("libs", function(){ gulp.src(PATHS.libs).pipe(gulp.dest(PATHS.dist + "/libs")); }) gulp.task("html", function(){ gulp.src(PATHS.html).pipe(gulp.dest(PATHS.dist)); // .pipe(watch()) //.pipe(connect.reload()); }) gulp.task('ts2js', function () { var typescript = require('gulp-typescript'); var tsResult = gulp.src([PATHS.src, PATHS.typings]) .pipe(typescript({ noImplicitAny: true, module: 'system', target: 'ES5', emitDecoratorMetadata: true, experimentalDecorators: true })); return tsResult.js.pipe(gulp.dest(PATHS.dist)); }); gulp.task('play', ['html', 'libs', 'ts2js'], function () { var http = require('http'); var _connect = require('connect'); var serveStatic = require('serve-static'); gulp.watch(PATHS.src, ['ts2js']); gulp.watch(PATHS.html, ['html']); var app = _connect().use( serveStatic(path.join(__dirname, PATHS.dist)) ); http.createServer(app).listen(port, function () { open('http://localhost:' + port); }); }); // 自动刷新不可用 gulp.task('server',['html', 'libs', 'ts2js'],function(){ gulp.watch(PATHS.src, ['ts2js']); gulp.watch(PATHS.html, ['html']); open('http://192.168.2.120:' + port); connect.server({ port: port, root:PATHS.dist, livereload: true }); })
7.People模块为例, people-service.ts
import { Injectable } from "angular2/core"; import { Http,Response,Headers,RequestOptions } from 'angular2/http'; @Injectable() export class PeopleService{ names:Array<string>; url:string="http://localhost:10003/api/todo/"; constructor(private _http:Http){ // //fade initialize // this.names=[ // {Id:100,Key:"",Name:"Lisa",IsComplete:false,Desc:"homeless can you here me."}, // {Id:101,Key:"",Name:"Miskovsky",IsComplete:false,Desc:"calling back little bird."}, // {Id:102,Key:"",Name:"Jennifer",IsComplete:false,Desc:"Seattle is sunshine now."}, // {Id:103,Key:"",Name:"Lana Del Ray",IsComplete:false,Desc:"<<Summertime Sadness>>"}, // {Id:104,Key:"",Name:"Aili",IsComplete:false,Desc:"weibo english"}, // {Id:105,Key:"",Name:"July",IsComplete:false,Desc:"come with back love"}, // {Id:106,Key:"",Name:"Rlogue",IsComplete:false,Desc:"fall with you"} // ]; } //get from local getPeopleList(){ console.log("get date from server !"); return this.names; } //get info from local getPersonDetail(id:number){ return this.names.find(function(p){ return p.Id==id; }); } //get data from webapi getPeople(){ return this._http.get(this.url); // .map(res=>res.json.data) // .catch(function(error:Response){ console.log(error); }); } //get info from webapi getPerson(key:string){ return this._http.get(this.url+key); } addPerson(){ let body = JSON.stringify({ Id: 2, "Key": "dba980a7-555b-44b8-9043-91fc22adc00b", Name: "first todo item", "IsComplete": false, Desc: "desc content from first todo" }); let headers = new Headers({'Content-type': 'application/json;'}); let options = new RequestOptions({ headers: headers }); console.log(body); console.log(headers); console.log(options); return this._http.post(this.url, body, options).subscribe(resp=>console.info(resp);); } };
8.people列表模块 people.ts
import { Component } from "angular2/core"; import { bootstrap } from "angular2/platform/browser"; import { HTTP_PROVIDERS } from "angular2/http"; import { PeopleService } from "people/people-service.js"; import { ROUTER_PROVIDERS,RouteParams,Router} from "angular2/router"; import { InfiniteScroll } from "components/infinite-scroll/infinite-scroll.js"; @Component({ selector:"app-people", providers:[HTTP_PROVIDERS,PeopleService,Location], templateUrl:"people/people.html", // template:"<h1>PEOPLE</h1>", directives:[InfiniteScroll], styles:[`button {border: 1px solid Red;}`] }) export class _People implements OnInit{ name:string; age:number; names:Array<string>; isBusy:boolean=false; constructor(private _people_service:PeopleService,private _router:Router){ this.name="Lisa Miskovsky"; this.age=27; //Observable _people_service.getPeople().subscribe(resp=>this.names=resp.json()); } SayHello(private _name:string){ this.name=_name; console.log("Hello IM:"+_name); } viewInfo(private _id:number){ this._router.navigate( ["Person", { id:_id }] ); } onScroll(){ console.log("scrolled :"+new Date().getTime()); if(this.isBusy) return; this.isBusy=true; console.log("busy:"+this.isBusy); // this.names=this.names.concat(this._people_service.getPeopleList()); this._people_service.getPeople().subscribe(resp=>this.names=this.names.concat(resp.json()); this.isBusy=false; console.log("busy:"+this.isBusy); console.log("load more over !"); } } export function render_people(){ bootstrap(_People, [ROUTER_PROVIDERS]).catch(err=>console.log(err)); }
9.people模块的页面展现(模拟滚动加载)
<section style="margin-top: 20px;"> <div infinite-scroll style="height:500px;overflow-y: scroll;" [infiniteScrollDistance]="1" [infiniteScrollThrottle]="500" (scrolled)="onScroll()" [scrollWindow]="false"> <div *ngFor="#person of names;#_index=index"> <p *ngIf="person" style="height:auto;border:1px solid #000;padding:5px;"> {{_index+1}}、{{person.Id}}-{{person.Name}} <br/> <span>{{person.Key}}</span><br/> <span>{{person.Desc}}</span><br/> <button (click)="SayHello(person.Name)">SayHello</button> <button (click)="viewInfo(person.Key)">ViewInfo</button> </p> </div> </div> </section>
11.源码
http://git.oschina.net/gaojinbogit/ng2-demo
12.angualr2 typescript学习资料
--ng2.0
文件上传api http://valor-software.com/ng2-file-upload/
系列博客 http://www.cnblogs.com/1wen/p/5446863.html
快速上手 http://cnodejs.org/topic/55af2bc4911fb957520eacef
推酷站点 http://www.tuicool.com/articles/mi6rmuB
中文社区 http://www.angularjs.cn/A2pG
语法清单 https://segmentfault.com/a/1190000004071388
深度开源 http://www.open-open.com/lib/list/396
一些资料 https://segmentfault.com/a/1190000003761054
大量资料 https://github.com/timjacobi/angular2-education
1.x升级2 http://www.wtoutiao.com/p/C34jXG.html
--typescript
ES6简介 http://es6.ruanyifeng.com/#docs/intro
博客 http://www.cnblogs.com/smartkid/archive/2012/10/05/A_First_Look_Of_TypeScript.html
系列教程 http://www.cnblogs.com/tansm/p/TypeScript_Handbook_Enums.html
GitBook https://www.gitbook.com/book/zhongsp/typescript-handbook/details
tsc转职 http://www.cnblogs.com/crazylights/p/5234884.html