《Angular4从入门到实战》学习笔记
腾讯课堂:米斯特吴 视频讲座
二〇一九年二月十三日星期三14时14分
What Is Angular?(简介)
前端最流行的主流JavaScript框架;
由谷歌倾情打造并维护;
致力于构建单页面应用(SPA);
是主流MEAN综合框架中的一部分;
打破HTML静态,创建动态的WEB应用。
不是一个服务端的框架或技术;不是JS的一个库,例如jQuery,React等;不是用于设计;不是一个平台或一门语言;不是一个插件。(非常好)
Why Use Angular?(优点)
可以快速开发及代码迭代;(相对于瀑布模型,就是开发过程用户可见,先开发一个雏形,再迭代开发)
所有代码都通过组件实现(模块化)
动态获取数据内容;
跨平台
ECMAScript 6(以下简称ES6)是JavaScript语言的下一代标准,已经在2015年6月正式发布了。
TypeScript:
是JavaScript的超集;微软创建及维护;拥有具体的类型;面向对象;与JavaC#相似
Components(组件):
在Angular4中都是以组件式开发;在组件中包含选择器,模板等;当前的类用户处理逻辑。
安装:AngularCLI(脚手架)或从github中拉取并使用
依赖的环境:NPM&NODE:也就是安装node
从官网安装并测试安装成功否:node -v
由于Angular CLI的一些资源被墙掉了,所以,要使用淘宝镜像下载安装,否则,慢且会主线问题。淘宝镜像:https://npm.taobao.org/。
命令行输入:npm install -g cnpm
再输入:npm install -g cnpm --registry=https://registry.npm.taobao.org
安装Angular Cli,命令行输入:cnpm install -g @angular/cli@latest
检验是否安装成功:ng help
Angular CLI的命令关键字为:ng
创建项目:第一步ng new Test 出现绿色字体Ctrl+C终止批处理,因为很卡或出错
第二步在项目文件夹输入 cnpm install 从淘宝镜像中安装
然后用VScode(Visual Studio Code)打开项目或别的软件打开。
官方网站指示:>npm install -g @angular/cli 换成cnpm install -g @angular/cli@latest
>ng new my-dream-app
>cd my-dream-app
>ng serve --open
持久使用:npm config set registry https://registry.npm.taobao.org
验证是否成功:npm config get registry 或npm info express
使用:npm install -g cnpm --registry=https://registry.npm.taobao.org
二〇一九年二月十三日星期三23时37分
Angular项目的目录结构:(网上摘录)
组件相关的概念:
1.组件元数据装饰器(@Component)
简称组件装饰器,用来告知Angular框架如何处理一个TypeScript类.
Component装饰器包含多个属性,这些属性的值叫做元数据,Angular会根据这些元数据的值来渲染组件并执行组件的逻辑
2.模板(Template)
我们可以通过组件自带的模板来定义组件的外观,模板以html的形式存在,告诉Angular如何来渲染组件,一般来说,模板看起来很像html,但是我们可以在模板中使用Angular的数据绑定语法,来呈现控制器中的数据。
3.控制器(controller)
控制器就是一个普通的typescript类,他会被@Component来装饰,控制器会包含组件所有的属性和方法,绝大多数的业务逻辑都是写在控制器里的。控制器通过数据绑定与模板来通讯,模板展现控制器的数据,控制器处理模板上发生的事件。
装饰器,模板和控制器是组件的必备要素。还有一些可选的元素,比如:
输入属性(@inputs):是用来接收外部传入的数据的,Angular的程序结构就是一个组件树,输入属性允许在组件树种传递数据 。提供器(providers):这个是用来做依赖注入的 。生命周期钩子(LifeCycle Hooks):一个组件从创建到销毁的过程中会有多个钩子会被触发,类似于Android中的Activity的生命周期 。样式表:组件可以关联一些样式表 。动画(Animations): Angular提供了一个动画包来帮助我们方便的创建一些跟组件相关的动画效果,比如淡入淡出等 。输出属性(@Outputs):用来定义一些其他组件可能需要的事件或者用来在组件之间共享数据
下面我们来看看模块文件
app.module.ts:这个文件表示模块
与AppComponent类似,模块也需要装饰器来装饰。
二〇一九年二月十四日星期四0时3分
腾讯课堂:米斯特吴 《Angular4从入门到实战》之第三讲《Angular4创建组件及设置属性》
运行刚刚创建的Angular项目,命令行进入到Angulara4app项目目录,输入ng serve --open
或推送出要显示的网页,或者在浏览器地址栏输入:http://localhost:4200/
感觉就是一个web网站在运行,更改index.html等相关文件内容,只要按保存都会自动触发浏览器更新。
项目执行的第一个文件就是项目目录a4app下src目录里面的index.html文件。
在index.html中是无法直接引入自定义的或其他的CSS文件的,必须把CSS文件引入到src目录中的styles.css文件中,此文件本身还可以定义样式(此文件一开始除了一行注释以外是空的)。如:@charset "UTF-8";@import "test.css";
感觉src目录下的app目录里面的这五个文件都挺重要的,尤其是这个app.component.ts,里面的title内容一变,网页上的标题立即跟着改变。
app.component.ts文件的内容:
import { Component } from '@angular/core';
@Component({
selector: 'app-root', /*表示该组件将展示在index.html中的<app-root>标签中*/
templateUrl: './app.component.html', /*声明该组件所应用的模板*/
styleUrls: ['./app.component.css'] /*声明模板所应用的渲染*/
})
export class AppComponent {
title = 'Hello 世界!';
}
只要是组件,都会在app目录下创建!
引用组件:先打开a4app中的readme.md,拷贝第11行的`ng generate component component-name`
再开起来一个终端(因为原来的终端正在运行WEB服务),目录切换到项目目录a4app下,输入刚刚拷贝的命令行:ng generate component 组件名; 也可以用简写的模式ng g c 组件名。
比如新建一个存放组件的文件夹及新建组件:ng g c components/user
于是:在app文件夹下新建了一个components目录,components目录又建了一个user目录,
user目录下面新建了四个文件,分别是组件css、html、ts、spec.ts其spec.ts用于测试的,没用
我们在根组件app的html文件中加入<app-user></app-user>
(因为user的ts文件指定的选择器就是app-user,这与index中设置标签< app-root >如出一辙)
然后,就可以修改user下的html文件的内容和设置ts文件的对应的属性了。
user目录下的app.component.ts
import { Component, OnInit } from '@angular/core';
@Component({
selector: 'app-user',
templateUrl: './user.component.html',
styleUrls: ['./user.component.css']
})
export class UserComponent implements OnInit {
name = "hemiah"; /*添加属性*/
constructor() { } /*自动创建了两个空的方法*/
ngOnInit() { }
}
比如添加了一个name属性。然后,我们就可以在html中用{{name}}来调用这个name属性的值。
user目录下的app.component.ts还可以这样写:
二〇一九年二月十四日星期四2时33分53秒
腾讯课堂:米斯特吴 《Angular4从入门到实战》之第四讲《Angular4操作数据(增删改查)》
user.component.html文件实例:
<h1>Hello {{name}}!</h1>
<!--数据绑定-->
<ul>
<li>年龄:{{age}}</li>
<li>邮箱:{{email}}</li>
<li>地址:{{address.city}}{{address.state}}{{address.street}}</li>
</ul>
<!--ngFor循环-->
<ul>
<li *ngFor="let hobby of hobbies;let i='index'">
{{i+1}}:{{hobby}} <!-- 好神奇-->
<button (click)="deleteHobby(i)">X</button>
</li>
</ul>
<!--事件-->
<button (click)="onClick()">点我</button>
<!--表单-->
<form (submit)="addHobby(hobby.value)">
<div>
<label for="hobby">爱好:</label>
<input type="text" #hobby> <!-- #号是必须的,名字可以自由起-->
</div>
</form>
<hr>
<button (click)="toggleEdit()">是否编辑用信息</button>
<!--编辑表单-->
<div *ngIf="isEdit"> <!--控制div组件是否可见-->
<h1>编辑用户信息</h1>
<form>
<div>
<label for="name">姓名:</label>
<input type="text" [(ngModel)]="name" name="name"> <!--双向数据绑定实现编辑功能-->
<!--使用ngModel必须要在app下的app.module.ts文件中引入
import { FormsModule} from '@angular/forms';
还要在此文的imports:[]中添加上:FormsModule 注:Angular2是自动添加的-->
</div>
<div>
<label for="age">年龄:</label>
<input type="text" [(ngModel)]="age" name="age">
</div>
<div>
<label for="city">城市:</label>
<input type="text" [(ngModel)]="address.city" name="city">
</div>
</form>
</div>
user.component.ts文件实例:
import { Component, OnInit } from '@angular/core';
@Component({
selector: 'app-user',
templateUrl: './user.component.html',
styleUrls: ['./user.component.css']
})
export class UserComponent implements OnInit { /*最外层 包括此行以上,由系统自动生成*/
/*先定义属性*/
name: string;
age: number;
email: string;
address: Address;
hobbies: string[];
hello: any;
isEdit:boolean = false;
constructor() { /*在函数中注入依赖就可以作为类的属性被使用了*/
console.log("constructor ran ...");
}
ngOnInit() { /*此方法内给属性赋值,系统生成的空函数*/
console.log("ngOnInit ran ...");
this.name = "Hemiah";
this.age = 30;
this.email = "test@test.com";
this.address = {
street: "定泗路",
city: "北京",
state: "昌平区"
};
this.hobbies = ["写代码", "看电影", "听音乐"];
}
/*再定义方法*/
onClick() {
// console.log(123);
this.name = "Mr.Wu";
this.hobbies.push("New Hobby"); /*push追加到后面*/
}
addHobby(hobby){
// console.log(hobby);
this.hobbies.unshift(hobby); /* unshift插入到前面*/
return false;
}
deleteHobby(i){
this.hobbies.splice(i,1); /*splice删除,从下标开始1个项目*/
}
toggleEdit(){
this.isEdit= !this.isEdit;
}
} /*最外层*/
interface Address{ /*外层以外自定义数据类型*/
street:string,
city:string,
state:string
}
大致捋了一下执行过程:
1、 系统最先执行index.html,遇到其中的<app-root></app-root>标签则去执行
2、 app.component.ts文件声明的选择器selector:app-root。此文档的两个语句分别指向了两个文件
styleUrls: ['./app.component.css'];templateUrl: './app.component.html',
3、 执行./app.component.html,引出文件中的<app-user></app-user>标签,然后去执行
4、 user.component.ts文件中生命的选择器:selector:app-user。此文档包含两个语句:
styleUrls: ['./user.component.css'];templateUrl: './user.component.html',
5、最后执行:./user.component.html
ts文件类似于JavaScript文件,不过,困惑的是,为什么html文件中没有引用语句呢?
二〇一九年二月十四日星期四5时32分43秒
二〇一九年二月十四日星期四12时10分29秒
腾讯课堂:米斯特吴 《Angular4从入门到实战》之第五讲《Angular4核心功能Service》
What Is Service?
服务主要应用于多个组件中的数据管理;
可以让组件更干净;
DRY—Don't Repeat Yourself;
通过HTTP Module对数据进行增删改查。
创建服务的步骤:
创建一个新文件 /services/my-service.service.ts
import@Injectable并且创建class;
引入Service并添加到procide中;
任何组件需要使用需要引入并创建对象调用。
也使用命令创建Service:
ng g service services/my-service
会自动帮助我们创建文件以及写入对应的class
我们需要手动将Service添加到procider中
二〇一九年二月十四日星期四22时29分
腾讯课堂:米斯特吴 《Angular4从入门到实战》之第六讲《Angular4创建及使用Service》
Angular>a4app> ng g c components/home 创建一个新组件
ng serve --open 启动web服务
修改app.component.html 把标签换成:<app-home></app-home>指向新组件
在app目录下手动创建一个目录services,在目录中手动创建一个文件data.service.ts
手动添加初步代码如下:
import {Injectable} from '@angular/core'; /*引入Injectable*/
@Injectable() /*调用Injectable*/
export class DataService{ /*导出数据*/
users:string[];
constructor(){
this.users=["米斯特吴","Ac总有一天","吴海洋"]
}
getUsers(){
return this.users; /*准备给home.component.html返回数据*/
}
}
准备把data.service.ts中的数据返回给home.component.html
首先要在app.module.ts中要引入 import { DataService} from './services/data.service';
并放入此文件的提供器中:providers:[DataService], 这一行代码很重要!
接下来就可以使用了,比如在home.componet.ts中,先引入这个服务:
import { DataService} from '../../services/data.service';
然后改造已有的空构造函数constructor(){}如下:
users:string[];
constructor(public dataService:DataService) {
// console.log(this.dataService.getUsers());
this.users=this.dataService.getUsers();
}
然后就可以在home.componet.html中拿到home.componet.ts中的数据了!
<h1>Hello World!</h1>
<ul>
<li *ngFor="let user of users">
{{user}}
</li>
</ul>
这就是数据引入的全过程!
比如,在user组件中引入,第一步,在user.componet.ts中引入
import { DataService} from '../../services/data.service';
第二步:在constructor也创建好:constructor(public dataService:DataService){}
然后,返回home.componet.ts定义一个数组:users:string[];
然后再回到user.componet.ts中定义一个数组如下:
users:string[];
constructor(public dataService:DataService) {
this.users=this.dataService.getUsers();
}
其实就是改造user.componet.ts文件,添加引入,定义构造函数引入,然后引入!
接下在在user.componet.html中加入home.componet.html中的类似语句的数据引用,数据就顺利的引入到了user.componet.html中来了。
最后,最后,来到app.componet.html中,通过修改标签<app-user></app-user>或是<app-home></app-home>就可以重定向选择器,来拿取不同的数据了。这样就达到数据统一管理的目的!!!!!
接下来的例子user是不用的,这里仅仅是演示数据的管理的便利性。
在html中引入一些好看的样式:
www.bootswatch.com
点击Cosmo的DOWNLOAD
出现页面:https://bootswatch.com/4/cosmo/bootstrap.min.css,拿到CDN(内容分发网络)也就是这个网址名字。
然后,在index.html中引入:
<link rel="stylesheet" href="https://bootswatch.com/4/cosmo/bootstrap.min.css">
然后修改html加上指定的class名,就起到了渲染的目的了:
<h1>Hello World!</h1>
<ul class="list-group">
<li class="list-group-item" *ngFor="let user of users">
{{user}}
</li>
</ul>
2/15/2019 1:03:35 AM
二〇一九年二月十五日星期五1时4分33秒
腾讯课堂:米斯特吴 《Angular4从入门到实战》之第七讲《Angular4 ES7中的观察者对象Observable》
ES7不隶属于Angular但后面的知识要用到它:
首先在data.service.ts中引入Observable: import {Observable} from 'rxjs';
然后定义一个新的数据类型:data:Observable<Array<number>>;然后修改getUsers(){}
getUsers(){
// return this.users; /*准备给home.component.html返回数据*/
this.data = new Observable(observer=>{
//让我们当前的data,等于新创建起来的Observable对象,对象里面会有对应的
//给我们传输的数据,括号里面的是回调函数,我们用箭头函数,在箭头函数中,
//我们想让它每隔1秒传输对应的数据,然后在我们的页面展示出来实时获取到的数据
//我们传的数据就相当于我们get请求的数据
setTimeout(()=>{ /*我们同样用回调函数*/
observer.next(1);
},1000);
setTimeout(()=>{
observer.next(2);
},2000);
setTimeout(()=>{
observer.next(3);
},3000);
setTimeout(()=>{
observer.next(4);
},4000);
setTimeout(()=>{
observer.complete();
},5000);
});
return this.data; /*这是非常关键的一个语句,用于返回数据 */
}
然后,在home.component.ts中引用数据:
data:any[]=[]; /*定义一个空数组*/
constructor(public dataService:DataService) {
// console.log(this.dataService.getUsers());
// this.users=this.dataService.getUsers();
//Observable
this.dataService.getUsers().subscribe(data=>{ /*用订阅者模式拿到数据*/
// console.log(data);
this.data.push(data); /*把data push进来*/
})
}
最后通过home.componet.html达到最终引用到页面之目的:(ts只能引用到控制台层面)
<h1>Hello World!</h1>
<ul class="list-group">
<li class="list-group-item" *ngFor="let d of data">
{{d}}
</li>
</ul>
这就是ES7中的Observable以后要用到的。 2/15/2019 2:45:13 AM
二〇一九年二月十五日星期五2时46分18秒
腾讯课堂:米斯特吴 《Angular4从入门到实战》之第八讲《Angular4使用Http中Get获取网络接口数据》
第一步:
在app.module.ts引入一个get请求:
Angular 4.3 版本后,推荐使用 HttpClient,可以参考 Angular HTTP Client 快速入门
所以,把import { HttpModule} from '@angular/http';
改为:import { HttpClientModule} from '@angular/common/http';
然后,在imports:[]中再引入一下:HttpClientModule
第二步:
在services中使用HTTP,打开:data.service.ts:先把把有关Observable的有关内容清除
然后引入HTTP:(视频中的老版本在我这新版本上还真的出问题,干脆百度一下,一次解决)
引入的命令为:import { HttpClient} from '@angular/common/http';
(视频中的为:import { Http} from '@angular/http';)
然后用constructor创建对象http(名字任意起),以后用这个对象来调用get,pot,post,delet等:
constructor(public http:Http){ }
然后:我们把请求的数据在getUsers(){}中return回去,get中就可以放请求数据的接口:
(模拟数据接口:打开网站http://jsonplaceholder.typicode.com/请求Resources的users)
return this.http.get("http://jsonplaceholder.typicode.com/users ")
返回数据时,其实是返回的观察者对象Observable要用到map方法,由于不能直接调用,所以,必须在文件头引入:import 'rxjs/add/operator/map'; 这一句老是报错!!!!!!取消就不会报错!
然后再getUsers(){}中加入.map(res=>res.json()); 这句也报错!!!只好也取消!
好像这两行取消了,后台依然能够抓取到网页的数据,是不是Angular新版本已经用HttpClient把这两个功能实现了呀?
接下来:在home.component.ts
constructor(public dataService:DataService) {
this.dataService.getUsers().subscribe(users=>{ /*观察者对象下的订阅者模式*/
console.log(users); 观察控制台的数据输出否?
})
}
如果数据输出正确,则注释掉控制台输出,添加如下代码:
constructor(之前):users:any[];
constructor中添加:this.users = users; 把订阅者模式抓取到的数据users赋给了本组件声明的数组users[]里面来了。users数组于是就有了数据,html就可以使用他们了。
最后,在home.component.html中添加:
<h1>Hello World!</h1>
<div *ngFor="let user of users">
<div class="well"> <!--因为在index.html已经引入了CSS模板-->
<ul class="list-group">
<li class="list-group-item">姓名:{{user.name}}</li>
<li class="list-group-item">邮箱:{{user.email}}</li>
<li class="list-group-item">电话:{{user.phone}}</li>
</ul>
</div>
</div>
这节课学得最费劲,因为搭建的版本与视频例题不一致,不知所以云,百度和思考花费了一些时间。
2/15/2019 6:08:21 AM
继续上面的app.module.ts出错处理:
好像还不行,改成这样就通过了,但就是pipe()这么写,我自己都不知道是啥意思!
import { map} from 'rxjs/operators';
.pipe(map(res => res));
下面这篇文章感觉挺权威了:
《从Angular 4开始,Angular的http请求改用HttpClient。》
添加HttpClientModule
首先需要引入HttpClientModule,它需要放在BrowserModule后:
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { HttpClientModule } from '@angular/common/http';
@NgModule({
imports: [
BrowserModule,
HttpClientModule,
],
declarations: [
AppComponent,
],
bootstrap: [ AppComponent ]
})
export class AppModule {}
请求JSON数据
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
@Injectable()
export class ConfigService {
constructor(private http: HttpClient) { }
getData() {
return this.http.get(this.dataUrl);
}
}
HttpClient其中一个特性是默认返回的数据为json数据。,使用它返回的数据如下:
http.get(url).subscribe(...)
对于angular 4之前,则需要做json转换:
http.get(url).map(res => res.json()).subscribe(...)
请求非JSON数据
如果需要返回非JSON数据,则需要在请求时设置responseType头信息为text:
getTextFile(filename: string) {
return this.http.get(filename, {responseType: 'text'})
.pipe(
tap(
data => this.log(filename, data),
error => this.logError(filename, error)
)
);
}
http.get()返回的是一个Observable<String>
2/15/2019 6:42:47 AM
结论是:在data.service.ts中的这两句没有必要添加了,因为HttpClient其中一个特性是默认返回的数据为json数据,从Angular4.X以后的版本,就不在需要如下设置啦:
import { Http} from '@angular/http';
.map(res=>res.json());
二〇一九年二月十五日星期五15时20分
腾讯课堂:米斯特吴 《Angular4从入门到实战》之第九讲《Angular4使用Http中的Post传递数据》
先注释掉user中ts和html中的Observable,其实已经注释掉了,只是标注Observable注释标记而已
接下来开始操作home.component.html文件了......
<h1>Hello World!</h1>
<div class="container">
<form (submit)="onSubmit()"> <!--添加一个form和提交触发事件-->
<div class="form-group">
<label>姓名</label>
<input type="text" class="form-control" [(ngModel)]="user.name" name="name">
</div>
<div class="form-group">
<label>邮箱</label>
<input type="text" class="form-control" [(ngModel)]="user.email" name="email">
</div>
<div class="form-group">
<label>电话</label>
<input type="text" class="form-control" [(ngModel)]="user.phone" name="phone">
</div>
<input type="submit" class="btn btn-success" value="提交">
</form>
<hr>
<div *ngFor="let user of users">
<div class="well"> <!--因为在index.html已经引入了CSS模板-->
<ul class="list-group">
<li class="list-group-item">姓名:{{user.name}}</li>
<li class="list-group-item">邮箱:{{user.email}}</li>
<li class="list-group-item">电话:{{user.phone}}</li>
</ul>
</div>
</div>
</div>然后在home.component.ts中设计user对象并实现html中定义的onSubmit方法并自定义addUser()方法:
export class HomeComponent implements OnInit {
users:any[];
user = {
name:"",
email:"",
phone:""
}
constructor(public dataService:DataService) {
this.dataService.getUsers().subscribe(users=>{ /*观察者对象下的订阅者模式*/
// console.log(users); /*观察控制台数据是否正确输出*/
this.users = users;
})
}
onSubmit(){
this.dataService.addUser(this.user).subscribe(user=>{
// console.log(user); /*查看控制台输出*/
this.users.unshift(user); /*直接显示在html页面中*/
})
}
然后在data.service.ts中实现addUser这个方法:不再.map(res=>res.json())
addUser(user){
return this.http.post("http://jsonplaceholder.typicode.com/users",user)
}
2/15/2019 4:29:31 PM16:29:08
二〇一九年二月十五日星期五16时30分
腾讯课堂:米斯特吴 《Angular4从入门到实战》之第十讲《Angular4使用Http中的Delete删除数据》
在home.component.html中的ul标签后添加删除按钮
<button (click)="onDeleteClick(user.id)" class="btn btn-danger">删除</button>
然后在ts里面home.component.ts来实现onDeleteClick()方法:
onDeleteClick(id){
// console.log(id);
this.dataService.deleteUser(id).subscribe(res=>{
})
}
自定义一个方法deleteUser(id)。
然后,再在data.service.ts中实现这个deleteUser(id)方法:
deleteUser(id){
return this.http.delete("http://jsonplaceholder.typicode.com/users/"+id)
}
然后在ts里面home.component.ts来进一步实现onDeleteClick()方法的删除动作:
然后在ts里面home.component.ts来实现onDeleteClick()方法:
onDeleteClick(id){
// console.log(id);
this.dataService.deleteUser(id).subscribe(res=>{
for(let i=0;i<this.users.length;i++){
if(this.users[i].id==id){
this.users.splice(i,1);
}
}
})
}
这样就测试成功了。删除就可以操作了。不过,刷新页面,删除的数据又回来来了,是因为网站提供的数据是测试数据,不能被真正的删除。
2/15/2019 5:50:48 PM
二〇一九年二月十五日星期五19时48分
腾讯课堂:米斯特吴 《Angular4从入门到实战》之第11讲《Angular4使用Http中的put更新数据》
先在hpme.component.html添加编辑按钮:
<button (click)="onEditClick(user)" class="btn btn-danger">编辑</button>
第二步:在home.component.ts定义onEditClick()这个按钮:
由于编辑要与输入共用一个框,所以,要先定义:
isEdit:boolean=false;
然后:
onEditClick(user){
this.isEdit=true;
this.user=user; /*先把值传到输入框(编辑框)内*/
}
把onSubmit()赋参数:onSubmit(isEdit) 以接收其值,定义了一个新的方法updataUser(this.user)。
onSubmit(isEdit){
if (isEdit){ /*如果isEdit=true则执行put方法进行编辑编辑*/
this.dataService.updataUser(this.user).subscribe(user=>{
//删除当前的
for(let i=0;i<this.users.length;i++){
if(this.users[i].id==this.user.id){
this.users.splice(i,1);
}
}
//添加更新的
this.users.unshift(this.user);
})
} else { /*如果isEdit=fales则执行post方法*/
this.dataService.addUser(this.user).subscribe(user=>{
// console.log(user); /*查看控制台输出*/
this.users.unshift(user); /*直接显示在html页面中*/
})
}
}
把html中的form做相应修改:<form (submit)="onSubmit(isEdit)">
如果isEdit传过来的是false,则执行post;如果是true则执行put(编辑)!
为了让home.component.ts中心的方法updataUser(this.user)起作用,要在data.service.ts中进行设定:
updataUser(user){
return this.http.put("http://jsonplaceholder.typicode.com/users/"+user.id,user)
}
2/15/2019 9:07:15 PM
二〇一九年二月十五日星期五21时11分
腾讯课堂:米斯特吴 《Angular4从入门到实战》之第12讲《Angular4核心模块Router》
路由就是解决从一个视图到另一个视图的导航,也就是不经过网络请求,刷新页面的情况下跳转到另一个页面。速度非常快。
路由的基本步骤:
<base href>在index.html
引入路由模块
创建路由
设置路由出口
添加路由链接
首先在index.html中设置根路径:<base href="/">
导入路由模块:import { RouterModule,Routes } from '@angular/router';
添加路由模块:imports:[
BrowserModule,
RouterModule.forRoot(appRoutes)
],
创建路由:
const appRoutes:Routes = [
{ path: '',component:HomeComponent },
{ path: 'about',component:AboutComponent },
{ path: '**',component:pageNotFoundComponent }
];
创建路由链接:<a class="nav-link" href="#" routerLink="/">Home</a>
添加组件出口:<router-outlet></router-outlet>
第一步:先检视一下index.html中是否已经有了<base href="/">
第二步:到app.module.ts中添加路由模块:
import { RouterModule,Routes } from '@angular/router';
并把路由模块用一下:
imports:[
BrowserModule,
RouterModule.forRoot(appRoutes) 用forRoot来执行一下下面创建的路由appRoutes
],
并设置一个路由:
const appRoutes:Routes = [
{ path: '',component:HomeComponent },
{ path: 'user',component:UsertComponent }
];
第三步:在app.component.html中把<app-home></app-home>注释掉,然后添加一个出口:
<router-outlet></router-outlet>
这是,在地址栏输入:http://localhost:4200
将显示不同的网页。
不过,这个路由还不够智能,需要继续下面的步骤:
创建一个导航的组件:
在控制台,切换到D:Angulara4app>执行:ng g c components/navbar
PS D:Angulara4app> ng g c components/navbar
CREATE src/app/components/navbar/navbar.component.html (25 bytes)
CREATE src/app/components/navbar/navbar.component.spec.ts (628 bytes)
CREATE src/app/components/navbar/navbar.component.ts (269 bytes)
CREATE src/app/components/navbar/navbar.component.css (0 bytes)
UPDATE src/app/app.module.ts (985 bytes)
PS D:Angulara4app>
新建的navbar自动更新到了app.module.ts中去了,也就是,多了一条语句:
import { NavbarComponent } from './components/navbar/navbar.component';
@NgModule中的declarationts:[]也引入了一行:NavbarComponent
然后在navbar.component.html添加导航,为了便捷,到bootstrap网站抓一个导航过来:
百度bootstrap中文网www.bootcss.com àBootstrap3中文文档(v3.3.7)
à下载Bootstrapà点击右侧导航“实例精选”à点击Bootstrap框架的基本用法下面左侧窗口
à出现Bootstrap starter template页面后à右键查看源码,或Ctrl-U查看源码,或省去前面的所有步骤,直接在地址栏输入:view-source:https://v3.bootcss.com/examples/starter-template/ 查看源码,把导航的这部分拷贝到navbar.component.html中:
<nav class="navbar navbar-inverse navbar-fixed-top">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="#">Project name</a>
</div>
<div id="navbar" class="collapse navbar-collapse">
<ul class="nav navbar-nav">
<li class="active"><a href="#">Home</a></li>
<li><a href="#about">About</a></li>
<li><a href="#contact">Contact</a></li>
</ul>
</div><!--/.nav-collapse -->
</div>
</nav>
改造成:
<nav class="navbar navbar-light">
<div class="container">
<a class="navbar-brand" href="#">Angular4</a>
<div id="navbar" class="navbar-collapse">
<ul class="nav navbar-nav">
<li><a href="#" routerLink="/">Home</a></li>
<li><a href="#" routerLink="/user">User</a></li>
</ul>
</div>
</div>
</nav>
然后,我们在app.component.html中调用这个导航:
<app-navbar></app-navbar>
2/15/2019 11:56:14 PM(ul li的显示样式始终没搞明白!)
二〇一九年二月十六日星期六0时8分
腾讯课堂:米斯特吴 《Angular4从入门到实战》之第13讲《公益广告》
腾讯课堂:米斯特吴 《Angular4从入门到实战》之第14讲《Angular4核心模块Router参数》
路由参数就是在访问的网址上加上不同的参数而跳转到不同的页面。
第一步:再到a4app创建一个新组件:ng g c components/userDetail
第二步:在app.module.ts里除了自动更新的引入新组件,还要写路由参数:
const appRoutes:Routes = [
{ path: '',component:HomeComponent},
{ path: 'user',component:UserComponent},
{ path: 'user/:id',component:UserDetailComponent},
];
第三步:到user-detail.component.ts中获取路由参数:
import { Router,ActivatedRoute,Params} from '@angular/router';
并在contructor(){}做相关的定义:
constructor(
private route:ActivatedRoute,
private router:Router
) {
this.route.params.subscribe((params:Params)=>{
console.log(params.id);
})
}
到浏览器地址栏输入:http://localhost:4200/user/1,就可跳转到user-detail work!中,说明连接成功
接下来继续设置:
打开home.component.html设置a标签
<a class="btn btn-primary pull-right" [(routerLink)]="'/user/'+user.id">详情</a>
接下来根据我们的ID,请求其所对应的数据:在user-detail.component.ts
id:number;
this.route.params.subscribe((params:Params)=>{
// console.log(params.id);
this.id=params.id;
})
}
再把服务引进来:
import {DataService} from '../../services/data.service';
于是我们就可以在data.service.ts中的添加方法:
getSingleUser(id){
return this.http.get("http://jsonplaceholder.typicode.com/users/"+id)
}
接下来,在user-detail.component.ts调用这个方法:
public dataServicde:DataService,
ngOnInit() {
this.dataServicde.getSingleUser(this.id).subscribe((user)=>{
console.log(user);
})
}
再添加:user:object={};
最后,我们就可以在user-detail.component.html中实现这个代码:
<h1>用户详情</h1>
<ul class="list-group">
<li class="list-group-item">{{user.id}}</li>
<li class="list-group-item">{{user.name}}</li>
<li class="list-group-item">{{user.email}}</li>
<li class="list-group-item">{{user.phone}}</li>
<li class="list-group-item">{{user.website}}</li>
</ul>
顺利通过!
user-detail.component.ts完整代码:
import { Component, OnInit } from '@angular/core';
import { Router,ActivatedRoute,Params} from '@angular/router';
import {DataService} from '../../services/data.service';
@Component({
selector: 'app-user-detail',
templateUrl: './user-detail.component.html',
styleUrls: ['./user-detail.component.css']
})
export class UserDetailComponent implements OnInit {
id:number;
user:object={};
constructor(
public dataServicde:DataService,
private route:ActivatedRoute,
private router:Router
) {
this.route.params.subscribe((params:Params)=>{
// console.log(params.id);
this.id=params.id;
})
}
ngOnInit() {
this.dataServicde.getSingleUser(this.id).subscribe((user)=>{
// console.log(user);
this.user=user;
})
}
}
data.service.ts完整代码:
import {Injectable} from '@angular/core'; /*引入Injectable*/
import { HttpClient} from '@angular/common/http';
// import 'rxjs/add/operator/map'; HttpClient返回的就是json数据了,所以这个引入废弃了
@Injectable() /*调用Injectable*/
export class DataService{
constructor(public http:HttpClient){ /*创建对象http以此调用get、post等*/
}
getSingleUser(id){
return this.http.get("http://jsonplaceholder.typicode.com/users/"+id)
}
getUsers(){
return this.http.get("http://jsonplaceholder.typicode.com/users")
// .map(res => res.json()); HttpClient返回的就是json数据了,所以不再需要转换了
}
addUser(user){
return this.http.post("http://jsonplaceholder.typicode.com/users",user)
}
deleteUser(id){
return this.http.delete("http://jsonplaceholder.typicode.com/users/"+id)
}
updataUser(user){
return this.http.put("http://jsonplaceholder.typicode.com/users/"+user.id,user)
}
}
app.module.ts完整代码:
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { FormsModule} from '@angular/forms';
import { HttpClientModule} from '@angular/common/http';
import { RouterModule,Routes} from '@angular/router';
import { AppComponent } from './app.component';
import { UserComponent } from './components/user/user.component';
import { HomeComponent } from './components/home/home.component';
import { DataService} from './services/data.service';
import { NavbarComponent } from './components/navbar/navbar.component';
import { UserDetailComponent } from './components/user-detail/user-detail.component';
const appRoutes:Routes = [
{ path: '',component:HomeComponent},
{ path: 'user',component:UserComponent},
{ path: 'user/:id',component:UserDetailComponent},
];
@NgModule({
declarations: [
AppComponent,
UserComponent,
HomeComponent,
NavbarComponent,
UserDetailComponent
],
imports: [
BrowserModule,
FormsModule,
HttpClientModule,
RouterModule.forRoot(appRoutes)
],
providers: [DataService],
bootstrap: [AppComponent]
})
export class AppModule { }
本视频课程基本完结了,后面还有一个具体的代码
2/16/2019 1:24:23 AM
二〇一九年二月十六日星期六1时25分27秒总用时两天半 要熟练还得具体项目磨炼