创建项目 ng new 项目名
进入项目目录,安装依赖 cnpm install
运行 ng serve --open
cli 命令行界面 command-line interface
文件目录结构
创建组件到components下的news文件
ng g component components/news
[innerHTML] 解析html标签
scss里边写css,ts后台数据
普通循环 *ngFor=‘let item of 数组数据’ {{item}}
<ul>
<li *ngFor='let items of arr'>
{{items}}
li>
ul>
数组里边包含对象的循环,前端user数据的查询 [数组] {对象}
<ol>
<li *ngFor='let items of userList'>
{{items.username}}---{{items.age}}
li>
ol>
数组包含数组遍历
<ul *ngFor='let a of car'>
<h2>{{a.type}}h2>
<ul *ngFor='let b of a.list'>
<li>{{b.cara}}--{{b.price}}li>
ul>
ul>
属性绑定动态值加中括号[]
加外部图片,先在ts里声明,再引入,src加[]中括号
<img [src]='url' alt='aa'/>
遍历数组并显示索引
<h2>遍历数组并显示数据的索引h2>
<ul *ngFor='let item of arr,let key=index'>
<li>{{key}}--{{item.title}}li>
ul>
public flag:boolean=false; //ts
<div *ngIf='flag'>
<img src="assets/images/psc.jpg" alt="aa"/>
div>
<div *ngIf='!flag'>
<img [src]='url' alt='aa'/>
div>
<span [ngSwitch]='int'>
<p *ngSwitchCase=1>
支付成功
p>
<p *ngSwitchCase=2>
支付遇到问题
p>
<p *ngSwitchDefault>
请重试
p>
span>
<ul *ngFor='let items of arr,let key=index' [ngClass]="{'red':key==0,'blue':key==1}">
{{key}}--{{items.title}}
ul>
转换日期格式
public today:any= new Date();
{{today | date:'yyyy-MM-dd HH:mm:ss'}}
init 初始化
点击事件 (click)
<button (click)='run()'>点击事件button>
定义run函数 ngOnInit初始化函数
**键盘事件(keydown)**表单
<input (keydown)='down($event)' type="text">
获取dom节点 参数.target 前端绑定方法时必须传$event的参数
<button (click)='runEvent($event)'>点击我变红button>
runEvent(a){
//获取dom节点
a.target.style.color='red'
}
只是针对表单 ,Model改变影响视图,视图改变影响Model
引入表单相关的模块
import { FormsModule } from '@angular/forms';
导入模块
imports: [
BrowserModule,
FormsModule
],
<input type="text" [(ngModel)]='msg'> //括号绑定事件
{{msg}}
点击事件执行方法
1.获取dom元素的值
<div class=user_list>
<ul>
<li>姓名: <input type="text" id='username'> li>
ul>
<button (click)=dosubmit()>获取表单的值button>
div>
dosubmit(){
//指定参数的类型,否则value会报错
let name:any=document.getElementById('username');
console.log(name.value)
}
2.双向绑定
<li>姓名: <input type="text" id='username' [(ngModel)]='userlist.username'> </li>
管道,转换为json格式
<span>{{userlist | json}}</span>
单选框 双向绑定性别,点击男女时也会选中
<input type="radio" name='sex' value="1" id="sex1" [(ngModel)]='userlist.sex'><label for="sex1">男</label>
<input type="radio" name="sex" value="2" id="sex2" [(ngModel)]='userlist.sex'><label for="sex2">女</label>
下拉选择框
<select [(ngModel)]='userlist.city'>
<option *ngFor='let items of userlist.cityList'>{{items}}</option>
</select>
没有子元素的不能进行遍历,如input 必须加个标签,而select可以
多选框
<span *ngFor='let items of userlist.hobby,let key=index'>
<input type="checkbox" [(ngModel)]='items.checked' [id]="'check'+key">
<label [for]="'check'+key">{{items.title}}</label>
</span>
文本框 textarea
备注:
<textarea rows="10" cols="10" [(ngModel)]='userlist.mark'></textarea>
indexOf() 方法可返回某个指定的字符串值在字符串中首次出现的位置。
ndexOf() 方法对大小写敏感!
**注释:**如果要检索的字符串值没有出现,则该方法返回 -1。
*ngFor 和 *If 不能在一个标签
toDoList
监听键盘事件,回车就添加到历史,根据索引删除,双向绑定多选框的值,选中为1,未选为0,[hidden]选中对其隐藏
后台数据
public history:string;
historyList:any[]=[]
constructor() { }
ngOnInit(): void {
}
addhistory(e:any) {
//判断是否输入回车
if(e.keyCode==13){
//判断是否重复,-1未出现过
if(this.historyList.indexOf(this.history)==-1){
this.historyList.push({
title: this.history,
status: 0 //0表示代办,1表示已完成
})
//清零
this.history=''
}else{
this.history=''
}
}
}
delete(key:any){
this.historyList.splice(key,1)
}
前端
<h2>toDoListh2>
<div class='todo'>
<input type="text" [(ngModel)]='history' (keyup)='addhistory($event)'>
<hr>
<h3>待办事项h3>
<ul *ngFor='let items of historyList,let key=index' [hidden]='items.status==1'>
<li>
<input type="checkbox" [(ngModel)]='items.status'>
{{items.title}}
<button (click)='delete(key)'>删除button>
li>
ul>
<h3>已完成事件h3>
<ul *ngFor='let items of historyList,let key=index' [hidden]='items.status==0'>
<li>
<input type="checkbox" [(ngModel)]='items.status'>
{{items.title}}
<button (click)='delete(key)'>删除button>
li>
ul>
div>
将公共部分封装到一个服务,在主模块引入声明,其他模块使用时,先引入,再在初始化函数中传参声明
创建服务到services下的storage
ng g service services/storage
providers 提供,供应
在主配置文件中,app.module.ts引入服务
//引入服务
import {StorageService} from './services/storage.service'
在providers中声明,提供服务,声明(declarations)组件,导入(import)模块
providers: [StorageService],
在组件中使用时需要再次引入,然后再new //不推荐
官方推荐在初始化函数中传参
constructor(public stor:StorageService) {
stor.get();
}
localStorage用于持久化的本地存储,除非手动删除数据,否则会一直保存
JSON.parse() 方法用于将一个 JSON 字符串转换为对象,如
JSON.stringify()
方法是将一个JavaScript值(对象或者数组)转换为一个 JSON字符串,如
服务持久化设置
set(key:string,value:any){
localStorage.setItem(key,JSON.stringify(value))
}
get(key:string){
return JSON.parse(localStorage.getItem(key))
}
remove(key:string){
localStorage.removeItem(key)
}
在组件中的设置
//刷新时会调用onInit生命周期函数
ngOnInit(): void {
var a = this.stor.get('list');
if(a){
this.historyList=a
}
}
addhistory(e:any) {
//判断是否输入回车
if(e.keyCode==13){
//判断是否重复,-1未出现过
if(this.historyList.indexOf(this.history)==-1){
this.historyList.push({
title: this.history,
status: 0 //0表示代办,1表示已完成
})
//清零
this.history=''
}
this.stor.set('list',this.historyList)
}
}
//保存删除的结果
delete(key:any){
this.historyList.splice(key,1);
this.stor.set('list',this.historyList)
}
//发生改变时保存
changed(){
this.stor.set('list',this.historyList)
}
组件不可以调用组件(父子子组件除外),但可以调用服务
服务不可以调用组件,但也可以调用服务
1.原生js,在视图加载初始化的方法里边获取dom
//视图加载完成后执行的方法
ngAfterViewInit(): void {
//必须指定类型才能够有获取操作(.)
var getDom:any = document.getElementById('aa');
console.log(getDom.innerHTML);
getDom.style.color='red'
}
2.viewchild
给节点起名
在核心文件引入ViewChild,获取dom并指定变量及其类型
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-KQdjcmNv-1608103727143)(…/笔记图片/image-20201211091112103.png)]
获取节点是nativeElement
//视图加载完成后执行的方法
ngAfterViewInit(): void {
console.log(this.mybox.nativeElement);
this.mybox.nativeElement.style.color='red'
}
1.给dom节点起一个名字
2.在业务逻辑中引入ViewChild import { Component, OnInit,ViewChild } from '@angular/core';
3.写在类里边@ViewChild(‘节点名’) @ViewChild('box') mybox:any
4.ngAfterViewInit生命周期函数调用nativeElement获取dom this.mybox.nativeElement
获取子组件的实例
1.引入子组件并起名
2.在父组件业务逻辑中引入ViewChild import { Component, OnInit,ViewChild } from '@angular/core';
3.写在类里边,获取子组件 @ViewChild('header') child:any
4.调用子组件中的方法 this.child.run();
native 本地的
Input 使用注解时不需要传参
调用子组件时,子组件显示的值能够随父组件动态改变
接收值和方法一样,父组件绑定方法时无括号
1.现在父组件中引入子组件并传值 ‘父组件数据’
2.子组件导入input import { Component, OnInit,Input} from '@angular/core';
3.接收父组件的值 @Input() ctitle:any
4.前端显示 {{ctitle}}
获取整个父组件实例 直接为this
ViewChild 使用注解时需要传参
1.引入子组件并起名
2.在父组件业务逻辑中引入ViewChild import { Component, OnInit,ViewChild } from '@angular/core';
3.写在类里边,获取子组件 @ViewChild('header') child:any
4.调用子组件中的方法 this.child.run();
非父子之间的组件可以通过localStorage或服务传递数据
生命周期函数通俗的讲就是组件创建、组件更新、组件销毁的时候会触发的一系列的方法。当 Angular 使用构造函数新建一个组件或指令后,就会按下面的顺序在特定时刻调用这些生命周期钩子方法。
1.constructor :构造函数中除了使用简单的值对局部变量进行初始化之外,什么都不应该做。 (非生命周期函数)
2.ngOnChanges() 当 Angular(重新)设置数据绑定输入属性时响应。 该方法接受当前和上一属性值的 SimpleChanges 对象,当被绑定的输入属性的值发生变化时调用,首次调用一定会发生在 ngOnInit() 之前。
3.ngOnInit() 在 Angular 第一次显示数据绑定和设置指令/组件的输入属性之后,初始化指令/组件。在第一轮 ngOnChanges() 完成之后调用,只调用一次。
使用 ngOnInit() 有两个原因:
1、在构造函数之后马上执行复杂的初始化逻辑
2、在 Angular 设置完输入属性之后,对该组件进行准备。
有经验的开发者会认同组件的构建应该很便宜和安全。
4.ngDoCheck() 检测,并在发生 Angular 无法或不愿意自己检测的变化时作出反应。在每个 Angular 变更检测周期中调用,ngOnChanges() 和 ngOnInit() 之后。
5.ngAfterContentInit() 当把内容投影进组件之后调用。第一次 ngDoCheck() 之后调用,只调用一次。
6.ngAfterContentChecked() 每次完成被投影组件内容的变更检测之后调用。ngAfterContentInit() 和每次 ngDoCheck() 之后调用。
7.ngAfterViewInit() 初始化完组件视图及其子视图之后调用。第一次 ngAfterContentChecked() 之后调用,只调用一次。
8.ngAfterViewChecked() 每次做完组件视图和子视图的变更检测之后调用。ngAfterViewInit()和每次 ngAfterContentChecked() 之后
调用。
9.ngOnDestroy() 当 Angular 每次销毁指令/组件之前调用并清扫。在这反订阅可观察对象和分离事件处理器,以防内存泄漏。
在 Angular 销毁指令/组件之前调用。
RxJS 是 ReactiveX 编程理念的 JavaScript 版本。ReactiveX 来自微软,它是一种针对异步数据流的编程
。简单来说,它将一切数据,包括 HTTP 请求,DOM 事件或者普通数据等包装成流的形式,然后用强大丰富的操作符对流进行处理,使你能以同步编程的方式处理异步数据,并组合不同的操作符来轻松优雅的实现你所需要的功能。
RxJS 里面提供了很多模块。这里我们主要给大家讲 RxJS 里面最常用的 Observable 和fromEvent。
目前常见的异步编程的几种方法:
1、回调函数
2、事件监听/发布订阅
3、Promise
4、Rxjs
Promise 处理异步:
let promise = new Promise(resolve => {
setTimeout(() => {
resolve('---promise timeout---');
}, 2000);
});
promise.then(value => console.log(value));
RxJS 处理异步:
import {Observable} from 'rxjs';
let stream = new Observable(observer => {
setTimeout(() => {
observer.next('observable timeout');
}, 2000);
});
stream.subscribe(value => console.log(value));
从上面列子可以看到 RxJS 和 Promise 的基本用法非常类似,除了一些关键词不同。Promise里面用的是 then() 和 resolve(),而 RxJS 里面用的是 next() 和 subscribe()。Promise 和 RxJS 的用法基本相似。其实Rxjs相比Promise 要强大很多。
比如 Rxjs 中可以中途撤回、Rxjs 可以发射多个值、Rxjs 提供了多种工具函数等等。
Angular5.x 以后 get、post 和和服务器交互使用的是 HttpClientModule 模块。
1、在 app.module.ts 中引入 HttpClientModule 并注入
import {HttpClientModule} from '@angular/common/http';
imports: [
BrowserModule,
HttpClientModule
]
2、在用到的地方引入 HttpClient 并在构造函数声明
import {HttpClient} from "@angular/common/http";
在构造函数中声明
constructor(public http:HttpClient) { }
3、get 请求数据
var api = "http://a.itying.com/api/productlist";
this.http.get(api).subscribe(response => {
console.log(response);
});
Angular5.x 以后 get、post 和和服务器交互使用的是 HttpClientModule 模块。
1、在 app.module.ts 中引入 HttpClientModule 并注入
import {HttpClientModule} from '@angular/common/http';
imports: [
BrowserModule,
HttpClientModule
]
2、在用到的地方引入 HttpClient 、HttpHeaders 并在构造函数声明 HttpClient
import {HttpClient,HttpHeaders} from "@angular/common/http";
constructor(public http:HttpClient) { }
3、post 提交数据
固定写法,跨域
//固定写法
const httpOptions = {
headers: new HttpHeaders({ 'Content-Type': 'application/json' })
};
var api = "http://127.0.0.1:3000/doLogin";
this.http.post(api,{username:'张三',age:'20'},httpOptions).subscribe(response => {
console.log(response);
});
使用之前先测试接口支不支持jsonp格式
解决跨域的一种方式
在请求后边加上 ?callback=aaa,如果回显为一个方法则支持
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-IZItVwNC-1608103727144)(…/笔记图片/image-20201211162828067.png)]
1、在 app.module.ts 中引入 HttpClientModule、HttpClientJsonpModule 并注入
import {HttpClientModule,HttpClientJsonpModule} from '@angular/common/http';
imports: [
BrowserModule,
HttpClientModule,
HttpClientJsonpModule
]
2、在用到的地方引入 HttpClient 并在构造函数声明
import {HttpClient} from "@angular/common/http";
constructor(public http:HttpClient) { }
3、jsonp 请求数据
var api = "http://a.itying.com/api/productlist";
this.http.jsonp(api,'callback').subscribe(response => {
console.log(response);
});
1、安装 axios
cnpm install axios --save
2、用到的地方引入 axios
import axios from 'axios';
3、看文档使用
axiosData(){
var api='http://a.itying.com/api/productlist';
axios.get(api).then(function(response){
console.log(response)
})
}
1.创建项目时创建路由
2.在app-routing.module.ts导入
import { HomeComponent } from './components/home/home.component';
import { NewsComponent } from './components/news/news.component';
import { ProductComponent } from './components/product/product.component';
3.配置 const定义的变量不可以修改,而且必须初始化。与java final相似
const routes: Routes = [
{
path: 'home',
component:HomeComponent
},{
path:'news',
component:NewsComponent
},{
path:'product',
component:ProductComponent
}
];
4.直接跳转 ng-router-link 跳转的路由路径要加斜杠
<a [routerLink]="[ '/home' ]">name</a>
匹配不到路由时重定向到home页面 两个星 这个一定要放在路由配置的最下边,否则它下边的配置都不会生效
{
path:'**',
redirectTo:'home'
}
选中时改变颜色,设置类标签active的颜色即可
<a [routerLink]="['/home']" routerLinkActive='active'>name</a>
<a routerLink='/news' routerLinkActive='active'>新闻</a>
content 内容
传值的页面
<ul *ngFor='let items of list,let key=index'>
<li>
//传参,[queryParams]
<a [routerLink]="[ '/newcontent']" [queryParams]='{aaid:key}'> {{key}}---{{items}}</a>
</li>
</ul>
接收值的页面
先引入 import { ActivatedRoute } from '@angular/router';
再接收其值
//传参声明
constructor(public active:ActivatedRoute) { }
ngOnInit(): void {
//active.queryParams是Rxjs数据,需要subscribe
this.active.queryParams.subscribe((data)=>{
console.log(data)
})
}
传值的页面
<a [routerLink]="[ '/newcontent/', key ]">{{key}}---{{items}}</a>
接收值的页面
先引入 import { ActivatedRoute } from '@angular/router';
再接收其值
//传参声明
constructor(public active:ActivatedRoute) { }
ngOnInit(): void {
this.active.params.subscribe((data)=>{
console.log(data)
})
}
配置路由,传参,冒号不要忘记
{
path:'newcontent/:aid',
component: NewcontentComponent
}
动态路由
引入路由
//引入路由
import {Router} from '@angular/router'
声明路由,实现跳转
//声明路由
constructor(public router:Router) { }
ngOnInit(): void {
}
getContens(){
//路由跳转
this.router.navigate(['/content/','123'])
}
get传值
引入路由
//引入路由
import {Router,NavigationExtras} from '@angular/router'
声明路由,实现跳转,携带queryParams跳转
//声明路由
constructor(public router:Router) { }
ngOnInit(): void {
}
getJs(){
//携值跳转
let queryParams:NavigationExtras={
queryParams:{'pid':123}
}
this.router.navigate(['/home'],queryParams)
}
实现侧边栏的转换
styles.scss全局样式设置,根组件的css只对应根组件
设置子路由,引入模块
配置子路由,children是一个数组,里边包含对象,属性path,component
{
path:'home',
component:HomeComponent,
children:[
{
path:'set',
component:SettingComponent
},{
path: 'welcome',
component: WelcomeComponent
}
]
}
html页面,路由路径,/父路由/子路由
<div class="left">
<a [routerLink]="[ '/home/welcome']">欢迎</a>
<br>
<br>
<a [routerLink]="[ '/home/set']">系统设置</a>
</div>
<div class="right">
//挂载子路由
<router-outlet></router-outlet>
</div>
挂载子路由,将配置在要显示的区域
点击主页面直接显示其欢迎页面
配置路由,配置所有查找不到的路径到欢迎页面
children:[
{
path:'set',
component:SettingComponent
},{
path: 'welcome',
component: WelcomeComponent
},{
//配置所有查找不到的路由
path: '**',
redirectTo:WelcomeComponent
}
]
图片放在assets下的image文件下
Ctrl h 选择替换
1.建立基础页面样式,配置路由
2.设置服务,封装跳转域名,在跟模块中引入服务模块并声明
import { Injectable } from '@angular/core';
import {HttpClient} from "@angular/common/http";
@Injectable({
providedIn: 'root'
})
export class CommonService {
public domain:any='http://a.itying.com/'
constructor(public http:HttpClient) {
}
//封装get方法
get(api:any){
return new Promise((resove,reject)=>{
this.http.get(this.domain+api).subscribe((response:any)=>{
resove(response.result)
})
})
}
}
api接口地址
列表:http://a.itying.com/api/productlist
详情:http://a.itying.com/api/productcontent?id=5ac1a22011f48140d0002955
3.在根模块中引入数据处理模块
import {HttpClientModule,HttpClientJsonpModule} from '@angular/common/http';
imports: [
BrowserModule,
AppRoutingModule,
HttpClientModule,
HttpClientJsonpModule
]
4.引入服务并声明,通过服务中的get()方法获取结果
import { CommonService } from '../../services/common.service';
export class HomeComponent implements OnInit {
public api='api/productlist'
public list:any[]=[];
public domain:any='http://a.itying.com/'
constructor(public common:CommonService) { }
ngOnInit(): void {
var data=this.common.get(this.api).then((data:any)=>{
console.log(data);
this.list = data;
});
}
}
5.前台页面渲染
<div class="item" *ngFor="let item of list">
<h3 class="item_cate">{{item.title}}h3>
<ul class="item_list" >
<li *ngFor="let list of item.list">
<div class="inner">
<img src="{{domain+list.img_url}}" />
<p class="title">{{list.title}}p>
<p class="price">¥{{list.price}}p>
div>
li>
ul>
div>
携值跳转:动态路由或get传值
动态路由:
改变路由
{path:'pcontent/:id',component:PcontentComponent},
跳转
<a [routerLink]="[ '/pcontent',list._id]">
<img src="{{domain+list.img_url}}" />
<p class="title">{{list.title}}</p>
<p class="price">¥{{list.price}}</p>
</a>
接收页面 引入 import { ActivatedRoute } from '@angular/router';
声明,接收值
constructor(public active:ActivatedRoute) { }
ngOnInit(): void {
this.active.params.subscribe((response)=>{
this.requestsContent(response.id)
})
}
requestsContent(id:any){
var api='api/productcontent?id='+id;
this.common.get(api).then((response:any)=>{
console.log(response);
this.list=response[0]
})
}
渲染页面。
对于大型项目来说,有太多的组件、服务等要在根模块中配置,过程太过于繁琐,而且加载速度会大大折扣。于是就引出了模块功能,将各个组件、服务等封装到对应的模块,在根模块只引入其模块即可。
创建模块下的user模块:
ng g module modules/user
创建user模块下的组件:
ng g component modules/user/components/order
创建user根模块的组件:
ng g component modules/user
在根模块中引用其他模块中的组件,先要将它们在子模块中暴露
exports:[OrderComponent,AddressComponent,ProfileComponent,UserComponent],
创建user模块的服务:
ng g service modules/user/services/common
引入服务的声明:
import { CommonService } from './services/common.service';
providers:[CommonService]
根模块引入user模块:
import {UserModule} from './modules/user/user.module';
imports: [
BrowserModule,
AppRoutingModule,
UserModule
],
组件:创建模块,暴露对应组件,在根模块中导入其他模块
服务:创建服务,引入(提供)服务
实现懒加载
不用在根组件中引入模块或组件
创建带路由的模块:
ng g module modules/user --routing
配置模块组件:
ng g component modules/user
在user路由设置中 引入组件并配置路由,不用写跳转路由:
import { UserComponent } from './user.component';
const routes: Routes = [
{path:'',component:UserComponent}
];
实现跳转:
在跟路由中配置
{path:'user',loadChildren:'./modules/user/user.module#UserModule'}
阿里蚂蚁金服开发——UI框架
ng add ng-zorro-antd
安装框架,失败多试几遍即可
使用时导入对应的模块,如按钮模块
import { NzButtonModule } from 'ng-zorro-antd/button';
模块加载路由自动配置
引入 Layout布局时,里边包含其他模块都要引入
Grid栅格
<div nz-row>
<div nz-col nzSpan="12">col-12</div>
<div nz-col nzSpan="12">col-12</div>
</div>
一行24个格,24除以nzSpan等于一行的格数,12就是两个格子
引入模块之后要重新运行,否则会报错
elementUI
引入模块
import { ElModule } from 'element-angular'
依赖注入
BrowserAnimationsModule,ElModule.forRoot()
在styles.scss中引入css样式
@import "~element-angular/theme/index.css";