angular学习
angular基础培训
引用某个博主:
从市场占有率来看
Angular 与 React 的历史更长,而 Vue.js 是后起之秀,所以 Angular 与 React 都比 Vue.js 的市场占有率更高。
但需要注意的是,Vue.js 的用户增长速度很快,有迎头赶上之势。
从支持度来看
Angular 与 React 的背后是大名鼎鼎的 Google 公司和 Facebook 公司,而 Vue.js 属于个人项目。所以,无论是开发团队还是技术社区,Angular 与 React 都更有优势。
图形比较:
Google趋势
Google是国际上通用的主流搜索引擎,首先让我们看看来自于全球范围内,2019年热度
可以看到,在市场份额这块儿,react后来居上,angular其次,vue这个新贵目前所占还是偏少。根据stackoverflow(一个IT界比较权威的问答网站)2018年调查,知道angular的人占36.9%,27.8%的人了解React,几乎没人知道Vue。所以目前开发人员中的主流还是Angular和React。
百度指数
国内行情
稳居第一
创建项目
安装Angular-cli:
npm install -g @angular/cli
检测是否安装Angular-cli:
ng v
angular创建项目
创建项目
ng new angularDemo
进入目录安装依赖
cnpm install
启动项目
npm run start
打开项目
http://localhost:4200/
目录结构
|-- 文件名 // 说明
|-- 首层目录
|-- e2e // 自动化集成测试目录
|-- node_modules // npm/cnpm第三方依赖包存放目录
|-- src // 应用源代码目录
|-- .editorconfig // 不同编译器统一代码风格
|-- .gitignore // git中的忽略文件列表
|-- angular.json // Angular的配置文件
|-- browserslist // 配置浏览器兼容性的文件
|-- karma.conf.js // 自动化测试框架Karma的配置文件
|-- package-lock.json // 依赖包版本锁定文件
|-- package.json // 标准的npm工具的配置文件
|-- README.md // 项目说明的MakeDown文件
|-- tsconfig.app.json // app项目的TypeScript的配置文件
|-- tsconfig.json // 整个工作区的TypeScript配置文件
|-- tsconfig.spec.json // 用于测试的TypeScript配置文件
|-- tslint.json // TypeScript的代码静态扫描配置
|-- src目录
|-- app // 工程源码目录
|-- assets // 资源目录
|-- environments // 环境配置目录
|-- favicon.ico // header里的icon
|-- index.html // 单页应用的宿主HTML
|-- main.ts // 入口ts文件
|-- polyfills.ts // 不同浏览器兼容脚本加载
|-- karma.conf.js // 自动化测试框架Karma的配置文件
|-- style.css // 整个项目的全局css
|-- test.ts // 测试入口
|-- app目录
|-- app-routing.module.ts // app路由
|-- app.component.css // app的css
|-- app.component.html // app的html
|-- app.component.spec.ts // app的测试
|-- app.component.ts // app的组件
|-- app.module.ts // app的模块
|-- environments目录
|-- environments.prod.ts // 生产环境
|-- environments.ts // 开发环境
新建组件
cd 到指定目录下创建:
// 新建了一个名字叫test的组件
ng generate component news
// 简写
ng g c news
创建组件的同时创建目录:
// 新建了一个文件夹components,名字叫test的组件
ng generate component components/news
// 简写
ng g c components/news
当使用 ng语法创建组件时,创建的组件会自动在 app.module.ts 这个文件中声明;所以如果是手动创建组件的小伙伴,记得要在这个文件中导入且声明你新建的组件
基础语法
定义变量,声明属性
public title="头部信息"
public username:string='王茂铭'
public 共有 (默认) 可以在当前类中使用,也可以在类外使用
protected 保护类型 它只有在当前类和它的子类里可以访问
private 私有 只有在当前类才可以访问这个属性
public title = '我是一个组件';
msg = '我是组件的msg';
private username: string = '张三';
// 推荐
public student: any = '我是一个学生(数据)';
Angular插值
语法:{{ …变量和表达式}}
应用:应用于html内容
<h1 [innerHtml]="htmlStr"></h1>
Angular 绑定class
定义的class三种方式,跟VUE一致,会自动的将变量和原有的HTML的CLASS相加
<!-- 定义变量的方式 -->
<h1 class="abc" class="{{classStr}}">class1</h1>
<h1 class="abc" [class]="classStr">class2</h1>
<h1 [attr.class]="classStr">class3</h1>
Class变量类型
<!-- 变量类型 -->
<!-- 字符串模式 -->
<h1 [class]="classStr">class4</h1>
<h1 class="a" [class]="'str abc'">class4</h1>
<!-- 对象模式 -->
<h1 [class]="classObj">class5</h1>
<h1 [class]="{bgBlue:isShow}">class6</h1>
<!-- 数组模式 -->
<h1 [class]="['bgBlue','active','abc']">class7</h1>
<h1 [class]="classArr"></h1>
Angular 绑定style
<!-- style -->
<!-- style表达式类型 -->
<!-- 字符串变量 -->
<h1 [style]="styleStr"></h1>
<!-- 对象模式 -->
<h1 [style]="styleObj"></h1>
<!-- 橙色 -->
<h1 [style.height]="styleObj.width">h</h1>
<h1 [style.width]="colorAbc"></h1>
<h1 [style.width.px]="widthNum"></h1>
Angular 绑定事件
<!-- style -->
<!--
绑定事件:
由等号左侧写小括号加上事件名称,右边写调用的事件函数
-->
<button (click)="changeColor()">点击</button>
<button (click)="changeButton($event)">点击带参数</button>
Angular 条件渲染
<div *ngIf="person=='广东人'">
广东:1000人
</div>
<!-- 条件渲染,匹配多种情况 -->
<div [ngSwitch]="homeState">
<div *ngSwitchCase="'睡觉'">卧室</div>
<div *ngSwitchCase="'看电视'">客厅</div>
<div *ngSwitchCase="'吃饭'">餐厅</div>
<div *ngSwitchCase="'发呆'">阳台</div>
<div *ngSwitchDefault>厕所</div>
</div>
Angular 循环渲染
<!-- 列表循环 -->
<ul>
<li *ngFor="let item of arr">{{item}}</li>
</ul>
<!-- 列表循环获取索引值 -->
<ul>
<li *ngFor="let item of arr;let i=index">索引值:{{i}};内容:{{item}}</li>
</ul>
<!-- 将列表的内容传入事件 -->
<ul>
<li *ngFor="let item of arr;let i=index" (click)="choosePerson(item,i)">索引值:{{i}};内容:{{item}}</li>
</ul>
<!-- 循环复杂数组 -->
<ul>
<li *ngFor="let item of students;let key=index">{{key}}-{{item.name}}的爱好是{{item.hobby}}</li>
</ul>
双向数据绑定
input type="text" class="form-input" [(ngModel)]="userinfor.username">
管道(处理数据)
基础语法
<h1>{{student | json}}</h1>
<h1>显示时间:{{time | date:"yy/MM/dd"}}</h1>
<h1>用户名: {{username | uppercase}} </h1>
//管道可以转换多次
<h1>{{'abcdefg'|uppercase|lowercase}}</h1>
常用值:
1、大小写转换管道
uppercase将字符串转换为大写
lowercase将字符串转换为小写
<p>{{str | uppercase}}-{{str1 | lowercase}} </p> //str:hello str1:WORLD
页面上显示:HELLO-world
2、日期管道
date:日期管道符可以接受参数,用来规定输出日期的格式。
<p>现在的时间是{{today | date:'yyyy-MM-dd HH:mm:ss'}}</p>
today = new Date();
页面上显示:现在的时间是2019-04-02 16:08:10
3、小数管道
number管道用来将数字处理为我们需要的小数格式
接收的参数格式为{最少整数位数}.{最少小数位数}-{最多小数位数}
其中最少整数位数默认为1
最少小数位数默认为0
最多小数位数默认为3
当小数位数少于规定的{最少小数位数}时,会自动补0
当小数位数多于规定的{最多小数位数}时,会四舍五入
<p>num保留4位小数的值是:{{num | number:'3.2-4'}}</p>
num = 125.156896;
页面上显示:num保留4位小数的值是:125.1569
4、货币管道
currency管道用来将数字转换为货币格式
<p>数量:{{count}}</p>
<p>价格:{{price}}</p>
<p>总价:{{(price * count) | currency:'¥'}}</p>
count = 5;
price = 1.5;
页面上显示:
数量:5
价格:1.5
总价:$7.50
5、字符串截取
slice:start[:end] //开始下标到结束下标 不包括结束下标
<p>{{name | slice : 2 : 4}}</p>
name = '只对你说';
页面上显示:你说
6、json(数据)格式化
<div>
<p>{{ { name: 'semlinker' } | json }}</p>
</div>
页面上显示:{ "name": "semlinker" }
自定义管道
创建自定义的管道文件
ng g pipe filter/lcUppercase
书写管道方法
import { Pipe, PipeTransform } from '@angular/core';
@Pipe({
name: 'lcUppercase'
})
export class LcUppercasePipe implements PipeTransform {
transform(value: string, ...args: string[]): string {
console.log(args)
return '¥' + value + args[0];
}
}
模板
注意:msg是模板变量,lcUppercase是转换函数,:后面是参数
<h1>{{msg|lcUppercase:'元'}}</h1>
父子之间传参
父组件传值给子组件
父组件设置
<app-child [item]="sendchildMsg"></app-child>
子组件设置 (需要在子组件引入 Input)
import { Component, OnInit,Input } from '@angular/core';
@Component({
selector: 'app-child',
templateUrl: './child.component.html',
styleUrls: ['./child.component.css']
})
export class ChildComponent implements OnInit {
@Input() item;
constructor() { }
ngOnInit(): void {
}
}
子组件Template
<h1>{{item}}</h1>
子组件传值给父组件
父组件Template
<app-child (childMsg)="getEvent($event)"></app-child>
父组件Ts
import { Component } from '@angular/core';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
getChildMsg="";
getEvent(event){
console.log(event)
this.getChildMsg = event.msg
}
}
子组件设置(需要引入Output,EventEmitter)
import { Component, OnInit,Input,Output,EventEmitter } from '@angular/core';
@Component({
selector: 'app-child',
templateUrl: './child.component.html',
styleUrls: ['./child.component.css']
})
export class ChildComponent implements OnInit {
//实例化事件对象
@Output() childMsg=new EventEmitter()
constructor() { }
ngOnInit(): void {
}
sendMsg(){
//发送消息
this.childMsg.emit({msg:"我子组件,这是我发给父组件的消息"})
}
}
子组件Template
<button (click)="sendMsg()">发送消息给父组件</button>
父组件调用子组件的方法
父组件Template(需要在子组件的标签上添加 #child)
<app-news #child > </app-news>
<button type="button" (click)="getChildFun()">调用子组件方法按钮</button>
父组件Ts (需要引入ViewChild)
import { Component,ViewChild } from '@angular/core';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss']
})
export class AppComponent {
//注册
@ViewChild('child')
child;
getChildFun(){
this.child.sendMsg()
}
}
子组件
import { Component, OnInit,} from '@angular/core';
@Component({
selector: 'app-news',
templateUrl: './news.component.html',
styleUrls: ['./news.component.scss']
})
export class NewsComponent implements OnInit {
constructor() { }
ngOnInit(): void {
}
//子组件的方法
sendMsg(){
console.log("这是子组件的方法")
}
}
子组件调用父组件的方法(和子传父一样)
父组件Template
<h1>{{title}}</h1>
<app-news (parentFun)="parentFun()" > </app-news>
父组件Ts
import { Component,ViewChild } from '@angular/core';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss']
})
export class AppComponent {
title = '父组件';
parentFun(){
console.log("这是父组件的方法")
}
}
子组件Template
<p>子组件</p>
<button type="button" (click)="getParentFun()">点击触发父组件的方法</button>
子组件Ts
<p>子组件</p>
import { Component, OnInit,Output,EventEmitter } from '@angular/core';
@Component({
selector: 'app-news',
templateUrl: './news.component.html',
styleUrls: ['./news.component.scss']
})
export class NewsComponent implements OnInit {
constructor() { }
ngOnInit(): void {
}
@Output() parentFun=new EventEmitter()
getParentFun(){
this.parentFun.emit()
}
}
生命周期
<p>子组件</p>
import { Component } from '@angular/core';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
title = 'angularapp';
constructor(){
console.log("组件构造函数调用")
}
//指令有效
ngOnChanges(){
//console.log("数据发生变化之时就会调用此函数ngOnChanges")
}
ngOnInit(){
console.log("第一次显示数据绑定和指令输入属性之后,就会调用,只调用一次")
}
ngDoCheck(){
console.log('在ngOnChanges和ngOnInit发生之后,会进行一次检测')
}
ngAfterContentInit(){
console.log('数据内容渲染到视图上之后')
}
ngAfterContentChecked(){
console.log('数据内容渲染到视图检测之后')
}
ngAfterViewInit(){
console.log('完成组件和子组件初始化')
}
ngAfterViewChecked(){
console.log('完成组件和子组件初始化检测后')
}
ngOnDestory(){
console.log("销毁组件")
}
}
自定义指令
创建指令文件:
<p>子组件</p>
ng g directive directive/lcstyle
设置指令内容和功能 lcstyle.ts
import { Directive,Input,ElementRef } from '@angular/core';
@Directive({
selector: '[appLcstyle]'
})
export class LcstyleDirective {
@Input() appLcstyle;
constructor(public ref:ElementRef) {
console.log('constructor')
}
ngOnChanges(){
//console.log('指令')
//console.log("数据发生变化之时就会调用此函数ngOnChanges")
//console.log(this.appLcstyle)
//console.log(this.ref)
this.ref.nativeElement.className = this.appLcstyle;
this.ref.nativeElement.innerHTML = this.appLcstyle;
this.ref.nativeElement.addEventListener("click",()=>{
this.ref.nativeElement.style.background="pink"
})
}
}
使用
<p>子组件</p>
<h1 [appLcstyle]="'aaa'"></h1>
Axios的使用
第一步:安装axios
<p>子组件</p>
npm install axios
第二步:声明axios 在需要用到的地方
import axios from ‘axios’
第三步:使用方法
import axios from ‘axios’
//Angular生命周期:初始化
ngOnInit(){
axios.get("路径").then(res=>{
console.log(res)
}).catch((err)=>{
console.log(err);
}).finally(()=>{
console.log('执行完了');
});
}
路由
基础语法
1、创建路由指令
生成的 app-routing.module.ts 和 app-routing.module.spec.ts 是与 app.module.ts 在同一目录下的,也就是都在app目录下
ng generate module app-routing --flat --module=app
路由配置app-routing.module.ts
import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
import {IndexComponent} from './view/index/index.component';
import {AboutComponent} from './view/about/about.component';
import {NewsComponent} from './view/news/news.component'
//配置路由对象
const routes: Routes = [
{
//不需要加/
path:"",
component:IndexComponent
},
{
path:'about',
component:AboutComponent
},
{
path:"news",
component:NewsComponent
}
];
@NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule]
})
export class AppRoutingModule { }
HTML模板
<!-- 根据路径的变化,显示不同组件 -->
<style>
div>span{
margin: 20px;
padding: 5px 10px;
background-color: skyblue;
}
</style>
<div>
<span [routerLink]="['/']" routerLinkActive="router-link-active" >首页</span>
<span [routerLink]="['/about']" routerLinkActive="router-link-active" >about</span>
<span [routerLink]="['/news']" routerLinkActive="router-link-active" >news</span>
</div>
<router-outlet></router-outlet>
子路由
{
path:'admin',
component:AdminComponent,
children:[
{
path:'user',
component:UserComponent
},
{
path:'product',
component:ProductComponent
}
]
},
HTML模板设置
<p>admin works!</p>
<div class="admin">
<div class="left">
这是侧边栏
<div [routerLink]="['/admin/user']" routerLinkActive="router-link-active" >user</div>
<div [routerLink]="['/admin/product']" routerLinkActive="router-link-active" >product</div>
</div>
<div class="main">
<router-outlet></router-outlet>
</div>
</div>
路由传参
动态路由
{
//动态路由
path:"news/:id",
component:NewsComponent
},
获取动态路由的参数(需引入ActivatedRoute)
import { Component, OnInit } from '@angular/core';
//导入route
import {ActivatedRoute} from '@angular/router'
@Component({
selector: 'app-news',
templateUrl: './news.component.html',
styleUrls: ['./news.component.less']
})
export class NewsComponent implements OnInit {
title = ""
//注入route
constructor(public route:ActivatedRoute) {
}
ngOnInit(): void {
//let params = this.route.params;
//console.log(params.value.id);
}
goParams(){
//使用参数
this.route.params.subscribe((params)=>{
console.log(params)
this.title = params.id;
})
}
}