进一步理解angular

在上一篇文章中我介绍了安装和结构,以及运行过程。
https://blog.csdn.net/weixin_42603009/article/details/94382945
我们进一步理解其中的数据单向、双向、组建传值、Modules等的理解。
将你新建的项目用vs或者webStorm打开。
查看package.json,找到scripts中的运行命令运行。(另外这个json中还有依赖的包)
在这里插入图片描述
运行后访问:http://localhost:4200/
这里面有教你如何快速创建组件,添加UI组件,添加依赖。

ng generate component xyz  ---快速创建组件
ng add @angular/material   --添加UI组件
ng add @angular/pwa      --PWA(Progressive Web App,渐进式网页应用)是一种理念,使用多种技术来增强web app的功能,可以让网站的体验变得更好,能够模拟一些原生功能,比如通知推送。在移动端利用标准化框架,让网页应用呈现和原生应用相似的体验。
ng add _____   添加依赖的,+依赖名字

在这里插入图片描述
了解完基础。我们开始进一步理解。
1,快速创建组件(Modules):(注意需要选择好目录)
比如:组件是父子关系是相对关系。
此外还有如下命令(他们也有各自属性,用时了解):

ng generate class my-new-class: 新建 class
ng generate component my-new-component: 新建组件
ng generate directive my-new-directive: 新建指令
ng generate enum my-new-enum: 新建枚举
ng generate module my-new-module: 新建模块
ng generate pipe my-new-pipe: 新建管道
ng generate service my-new-service: 新建服务

在这里插入图片描述
创建好后我们来分析下:
在这里插入图片描述
因此我们就可以在app.component.html中使用:
在这里插入图片描述
运行结果如下:
在这里插入图片描述
那么如果我想在mymodule1中用my-input又该如何?我们可以看到MyInputComponent也在app中申明了。换句话来所,我们模拟它的运行过程,自定给my-input建module文件。如下面过程。(推荐使用第二种)

首先到指定目录下创建:

G:\angularStu\myAngular>cd src

G:\angularStu\myAngular\src>cd APP

G:\angularStu\myAngular\src\app>CD owncomponent
// 这里可以使用mkdir创建一个目录。

G:\angularStu\myAngular\src\app\owncomponent>ng generate component my-input
CREATE src/app/owncomponent/my-input/my-input.component.html (23 bytes)
CREATE src/app/owncomponent/my-input/my-input.component.spec.ts (636 bytes)
CREATE src/app/owncomponent/my-input/my-input.component.ts (282 bytes)
CREATE src/app/owncomponent/my-input/my-input.component.css (0 bytes)
UPDATE src/app/app.module.ts (682 bytes)

// 上面方法过于麻烦。其实你还可以这样。目录也跟着创建了(推荐使用)
G:\angularStu\myAngular>ng g component components/header
CREATE src/app/components/header/header.component.html (21 bytes)
CREATE src/app/components/header/header.component.spec.ts (628 bytes)
CREATE src/app/components/header/header.component.ts (275 bytes)
CREATE src/app/components/header/header.component.css (0 bytes)
UPDATE src/app/app.module.ts (770 bytes)

G:\angularStu\myAngular>


如何创建:
在这里插入图片描述
对hmtl经行编写:

<p>my-input works!</p>
<input type="text" placeholder="请输入姓名">

在这里插入图片描述
运行结果:
在这里插入图片描述
放在app.component.html中也是可以的。

<div>
<app-mymodule1></app-mymodule1>
  <app-mymodule2></app-mymodule2>
  <app-my-input></app-my-input>
</div>

运行结果:
在这里插入图片描述

这里特别再强调一点。如上我早my-app中要用到FormsModule组件。我们必须取它所在module中sheng’ming声明。再app.module.ts中是不会有用的。
到此组件创建和引用,以及外部组件引用的细节都知道了。

2,路由:页面的跳转。
路由:路由就是根据不同url地址。动态的让根组件挂载其他组件来实现一个单页面应用。
1,创建组件,并在app-routing.module.ts添加路由:

import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
import {AppComponent} from './app.component';
import {AdminComponent} from './components/admin/admin.component';
import {HomeComponent} from './components/home/home.component';
import {NewsComponent} from './components/news/news.component';

// 自定义路由
const routes: Routes = [
  //不要写成‘/admin’
  {path: 'admin', component: AdminComponent},
  {path: 'home', component: HomeComponent},
  {path: 'news', component: NewsComponent},
  // 默认路由
  {
    path: '',
    redirectTo: '/home',
    pathMatch: 'full'
  },
];

@NgModule({
  imports: [RouterModule.forRoot(routes)],
  exports: [RouterModule]
})
export class AppRoutingModule { }

路由跳转方式:


<style>

</style>
<div>根组件</div>
<div>
   <!--两种方式,一个静态,一个动态,效果一样。这里要加/-->
  <!--  routerLinkActive="active" 是实现选中-->
  <a [routerLink]="['/news']" routerLinkActive="active">去到news</a><br>
  <a routerLink="/admin" routerLinkActive="active">去到admin</a>
<router-outlet></router-outlet>

访问结果:
在这里插入图片描述
那么跳转如何传值呢?
首先我们新建一个newsDetail看靠如上配置路由。实现有news到newsDetail传值。
1.get方式传值:[queryParams]="data"的方式。
news组件中:

<p>news works!</p><br><br><br>
<a [routerLink]="['/newsDetails']" [queryParams]="data">跳转到newsDetails</a>
<!--下面的也是可以的-->
<!--<a routerLink="/newsDetails" [queryParams]="data">跳转到newsDetails</a>-->
<--推荐使用下面这种-->
<!--<a [routerLink]="['/newsDetails', data]">跳转到newsDetails</a>-->
import { Component, OnInit } from '@angular/core';

@Component({
  selector: 'app-news',
  templateUrl: './news.component.html',
  styleUrls: ['./news.component.css']
})
export class NewsComponent implements OnInit {
  public data: any = {
    zhouyi: '真帅',
  }
  constructor() { }

  ngOnInit(): void {
  }

}

点击结果:
在这里插入图片描述
newDetails界面获取值:

import { Component, OnInit } from '@angular/core';
// 1.引入ActivatedRoute
import {ActivatedRoute} from '@angular/router';

@Component({
  selector: 'app-news-details',
  templateUrl: './news-details.component.html',
  styleUrls: ['./news-details.component.css']
})
export class NewsDetailsComponent implements OnInit {
  constructor(
    public route: ActivatedRoute
  ) { }

  ngOnInit(): void {
   // 2.获取方式。和我们的http请求是类似的。
    this.route.queryParams.subscribe((data) => {
      console.log(data);
    });
    // 如果第三种是params获取
    // this.route.params.subscribe((data) => {
    //   console.log(data);
    // });
  }
}

2.js方法中跳转。
新建一个adminLogin组件。同上路由配置等。
admin组件:

<p>admin works!</p>
<br><br><br>
<button (click)="goToAdminDetails()">跳转到adminDetail</button>
import { Component, OnInit } from '@angular/core';
// 1.引入Router get传值用NavigationExtras
import {Router, NavigationExtras} from '@angular/router';

@Component({
  selector: 'app-admin',
  templateUrl: './admin.component.html',
  styleUrls: ['./admin.component.css']
})
export class AdminComponent implements OnInit {

  public data: any = [1, 2, 3];
  // 2.构造(先写构造)
  constructor(public router: Router) { }

  ngOnInit(): void {
  }

  goToAdminDetails(): void {
    // 3.路由跳转
    // this.router.navigate(['/adminLogin/', this.data]);
    // get方式跳转.这个参数格式很严格。如下。
    // 当然不引入NavigationExtras也是可以的。
    // 比如 
    // let queryParams= {
    //  queryParams: {'aid': 123}
    // };
    let queryParams: NavigationExtras = {
      queryParams: {'aid': 123}
    };
    this.router.navigate(['/adminLogin'], queryParams);
  }
}

结果:
在这里插入图片描述
重点父子路由(嵌套路由)的理解:
最简单的父子路由以CSDN举例:点击1,对应的2出现,2对应的3出现。也就是在1控制2,2控制3典型父子路由。
在这里插入图片描述
具体看如下图:
在这里插入图片描述
附上命令:

ng g component components/home
ng g component components/home/welcomeHome
ng g component components/home/systemSet
ng g component components/news
ng g component components/news/newslist
ng g component components/news/newsfast

结果:
在这里插入图片描述
这里我需要特意说明两点:
1、当前组件指定挂载组件位置:通过它根据需要挂载到位置。

<router-outlet></router-outlet>

2、全局样式最好放在styles.css下。
3,dom操作
首先,我回忆下原生js的操作。

// 我们用的是document操作,
// 比如:获取dom id = "tmpId" 也可以用class获取。
var dom = document.getElementById('tmpId');
dom.setAttribute('title','titleName'); // 各种属性都可以这么设置
dom.style.color='red';
dom.getAttribute('title'); // 结果为titleName
// 为<div id ="fileId"></div> 插入html
var str =<span>+ nihao + '</span>';
dom.innerHTML = str; // innerTEXT也是可以的。看你需求

// 另外我们获取的dom结构类似如下。这个就需要你有类似经验。
在这里插入图片描述
在angular中的dom操作 (ViewChild)。
1,首先给要获取的结点取名。形式: #name
consoleDom是用来获取结构的

<div #mymoudule>
  <p>mymodule1 works!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!</p>
  <p (click)="consoleDom()">test</p>
</div>

2,业务逻辑处理(对应的ts):

import {Component, ElementRef, OnInit, ViewChild} from '@angular/core';

@Component({
  selector: 'app-mymodule1',
  templateUrl: './mymodule1.component.html',
  styleUrls: ['./mymodule1.component.css']
})
export class Mymodule1Component implements OnInit {

  // 通过装饰器@ViewChild获取dom结点。 两种写法都可以推荐第一种。取出dom给了mydom
  @ViewChild('mymoudule') mydom: ElementRef;
  // @ViewChild('mymoudule') mydom: any;
  constructor() { }

  ngOnInit(): void {
  }

  consoleDom() {
    console.log(this.mydom);
  }
}

结果如下:
在这里插入图片描述
ViewChild的另一个更大的用处。父子组件通过ViewChild调用子组件。

<app-header #header></app-header>
<div #mymoudule>
  <p>mymodule1 works!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!</p>
  <p (click)="consoleDom()">test</p>
</div>
import { Component, OnInit } from '@angular/core';

@Component({
  selector: 'app-header',
  templateUrl: './header.component.html',
  styleUrls: ['./header.component.css']
})
export class HeaderComponent implements OnInit {

  constructor() { }

  ngOnInit(): void {
  }
  run() {
    console.log('我是子组件,该方法在父组件被调用');
  }
}
import {Component, ElementRef, OnInit, ViewChild} from '@angular/core';

@Component({
  selector: 'app-mymodule1',
  templateUrl: './mymodule1.component.html',
  styleUrls: ['./mymodule1.component.css']
})
export class Mymodule1Component implements OnInit {

  // 通过装饰器@ViewChild获取dom结点。 两种写法都可以推荐第一种。
  // 取出dom给了mydom
  @ViewChild('mymoudule') mydom: ElementRef;
  // 获取子组件
  @ViewChild('header') myheader: ElementRef; // 得到了子组件所有
  // @ViewChild('mymoudule') mydom: any;
  constructor() { }

  ngOnInit(): void {
  }

  consoleDom() {
    console.log(this.mydom);
    // 调用子组件的方法
    this.myheader.run();
  }

}

4,angular中css动画
侧边栏的实现:

G:\angularStu\myAngular>ng g component components/asidetranstion
CREATE src/app/components/asidetranstion/asidetranstion.component.html (29 bytes)
CREATE src/app/components/asidetranstion/asidetranstion.component.spec.ts (684 bytes)
CREATE src/app/components/asidetranstion/asidetranstion.component.ts (307 bytes)
CREATE src/app/components/asidetranstion/asidetranstion.component.css (0 bytes)
UPDATE src/app/app.module.ts (895 bytes)
<!-- * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -->
<!-- * * * * * * * * * * * The content below * * * * * * * * * * * -->
<!-- * * * * * * * * * * is only a placeholder * * * * * * * * * * -->
<!-- * * * * * * * * * * and can be replaced. * * * * * * * * * * * -->
<!-- * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -->
<!-- * * * * * * * * * Delete the template below * * * * * * * * * * -->
<!-- * * * * * * * to get started with your project! * * * * * * * * -->
<!-- * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -->

<style>

</style>

app.component.html

<div id="appID">
  <app-asidetranstion></app-asidetranstion>
</div>
<router-outlet></router-outlet>

asidetranstion.component.html:

<div id="content">


  主要内容
  <button (click)="showAside()">展示侧边栏</button>
  <button (click)="display()">展示侧边栏</button>
</div>
<aside #asideContent id="asideContent" style="width: 200px;height: 100%;position: absolute;right: 0px;top: 0px;background: red;transform: translate(100%,0);transition: all 2s">

  这是侧边栏
</aside>

asidetranstion.component.ts:

import {Component, ElementRef, OnInit, ViewChild} from '@angular/core';

@Component({
  selector: 'app-asidetranstion',
  templateUrl: './asidetranstion.component.html',
  styleUrls: ['./asidetranstion.component.css']
})
export class AsidetranstionComponent implements OnInit {

  @ViewChild('asideContent') myAside: ElementRef;
  constructor() { }

  ngOnInit(): void {
  }

  showAside() {
   // this.myAside.style.transform = 'transform(0,0)';
    document.getElementById('asideContent').style.transform = 'translate(0,0)';
  }
  display() {
    document.getElementById('asideContent').style.transform = 'translate(100%,0)';
  }
}

styles.css:

/* You can add global styles to this file, and also import other style files */
body{
  width: 100%;
  overflow-x: hidden;
}

5,父子组件通信(比较简单一笔带过)
1,父组件给子组件传值—@input: 不仅可以把数据传过去,还可以把自己的方法以及整个父组件传给子组件。
举个栗子:
父组件(父子):

// data代表值,也可以是方法。方法不能()表示直接执行。不带调用则执行。
<app-header [data]="data"></app-header>

子组件接收:

@input data:any; // ts中 就可以用了

2,父组件获取子组件值(前面已经讲了@ViewChild): 不仅可以把数据传过去,还可以把自己的方法以及整个父组件传给子组件。 也可以用:Output 和EvenEmitter
子组件实例化(子父):

// 配合使用 string指定类型
@Output() private outer: new EvenEmitter<string>();

// 在方法中将要给父组件的值发送出去
this.outer.emit('子组件的值传给父组件');

父组件接收:

<app-header (outer)="Menthod($event)"></app-header>

非父子组件的通信:推荐用service或者loaclstorage(推荐前者)

6,rxjs异步数据流遍程
它的强大体现在将一切数据,包装为数据流。它比promise更为强大。
异步遍程排序:回调函数,事件监听/发布订阅,Promise,Rxjs。
回调函数实现:
1,首先我们创建一个service:

G:\angularStu\myAngular>ng g service service/request
CREATE src/app/service/request.service.spec.ts (362 bytes)
CREATE src/app/service/request.service.ts (136 bytes)

2,在service方法中定义自己的方法:

import { Injectable } from '@angular/core';

@Injectable({
  providedIn: 'root'
})
export class RequestService {

  constructor() { }
  // t同步方法
  getData() {
    return '获取数据';
  }
  // 异步方法
  getCallbackData() {
    setTimeout(() => {
      return '异步方法';
    }, 1000);
  }
  // 异步方法,回调函数实现获取异步值
  getCallbackData111(cd) {
    setTimeout(() => {
      return cd('异步方法');
    }, 1000);
  }
}

3,在哪里用你就在哪里的constructor中说明引入。即可用。

import {Component, ElementRef, OnInit, ViewChild} from '@angular/core';
import {RequestService} from '../../service/request.service';

@Component({
  selector: 'app-asidetranstion',
  templateUrl: './asidetranstion.component.html',
  styleUrls: ['./asidetranstion.component.css']
})
export class AsidetranstionComponent implements OnInit {

  @ViewChild('asideContent') myAside: ElementRef;
  constructor(
    public request: RequestService
  ) { }

  ngOnInit(): void {
    console.log(this.request.getData());
    // 异步不能获取到,为undefined
    console.log(this.request.getCallbackData());
    // 异步回调实现
    this.request.getCallbackData111((data) => {
      console.log(data);
    });
  }

  showAside() {
   // this.myAside.style.transform = 'transform(0,0)';
    document.getElementById('asideContent').style.transform = 'translate(0,0)';
  }
  display() {
    document.getElementById('asideContent').style.transform = 'translate(100%,0)';
  }
}

结果如下:(这也跟缓存的原理有点类似)
在这里插入图片描述
2,promise实现(位置和上面一样,这是ES中自带的方式):

const promiseData = this.request.getPromiseData().then((data) =>{
    console.log(data)
  })
getPromiseData() {
    return new Promise((res => {
      setTimeout(() => {
        res('promise应用');
      });
    }));
  }

结果:
在这里插入图片描述
3。Rxjs实现异步(和promise很类似,结果省略):但是他可以取消订阅.unsubscribe()规定没返回就撤销。

  const promiseData = this.request.getObservableData().subscribe((data) =>{
    console.log(data);
  });
 getObservableData() {
    return new Observable((observe) => {
      setTimeout(() => {
        observe.next('observe调用数据');
      });
    });
  }

Rxjs还可以多次执行。比如一个请求每隔几秒发送一次。
异步请求封装定时器

getObservableData() {
    return new Observable((observe) => {
      // 每隔一秒出发一次
      setInterval(() => {
        const name = '张三';
        observe.next(name);
      }, 1000);
    });
  }

结果:
在这里插入图片描述
3,管道对map,filter的应用。
如果你懂java流操作,讲一下就会。
filter是对数据操作过滤;map是对数据进行操作改变:

 const promiseData = this.request.getObservableData().pipe(filter(value => {
    if (value % 2 == 0) {
      return true;
    }
  }), map(value => {
  // 比如在这里将对象转为json
    return  value*value;
  })).subscribe((data) =>{
    console.log(data);
  });

结果:
在这里插入图片描述
7,数据请求
通常我们会将请求封装都一个地方。
但无非是如下过程:
前提需要在app.module.ts引入模块支持。
在这里插入图片描述
get请求如下:

import {Component, ElementRef, OnInit, ViewChild} from '@angular/core';
import {RequestService} from '../../service/request.service';
// 引入HttpClient
import { HttpClient} from '@angular/common/http';

@Component({
  selector: 'app-asidetranstion',
  templateUrl: './asidetranstion.component.html',
  styleUrls: ['./asidetranstion.component.css']
})
export class AsidetranstionComponent implements OnInit {
  @ViewChild('asideContent') myAside: ElementRef;
  constructor(
    public request: RequestService,
    // 申明
    public http: HttpClient
  ) { }
  ngOnInit(): void {}

  httpRequest() {
    this.http.get('localhost:8080/test').subscribe((res: any) => {
      console.log(res);
    });
  }
 }

post如下(需要设置请求数据,header):

import {Component, ElementRef, OnInit, ViewChild} from '@angular/core';
import {RequestService} from '../../service/request.service';
// 引入HttpClient,HttpHeaders头组件
import { HttpClient, HttpHeaders} from '@angular/common/http';

@Component({
  selector: 'app-asidetranstion',
  templateUrl: './asidetranstion.component.html',
  styleUrls: ['./asidetranstion.component.css']
})
export class AsidetranstionComponent implements OnInit {
  @ViewChild('asideContent') myAside: ElementRef;
  constructor(
    public request: RequestService,
    // 申明
    public http: HttpClient,
    public header: HttpHeaders
  ) { }
  ngOnInit(): void {}

  httpRequest() {
    const header = {
      headers: new HttpHeaders({'Content-Type': 'application/json'})
    }
    this.http.post('localhost:8080/test', {'data':'数据'}, header).subscribe((res: any) => {
      console.log(res);
    });
  }
 }

jsonp(解决跨域请求的一种方式):
需要在app.module.ts引入模块支持;

import {HttpClientModule, HttpClientJsonpModule} from '@angular/common/http';
import {Component, ElementRef, OnInit, ViewChild} from '@angular/core';
import {RequestService} from '../../service/request.service';
// 引入HttpClient,HttpHeaders
import { HttpClient, HttpHeaders} from '@angular/common/http';

@Component({
  selector: 'app-asidetranstion',
  templateUrl: './asidetranstion.component.html',
  styleUrls: ['./asidetranstion.component.css']
})
export class AsidetranstionComponent implements OnInit {
  @ViewChild('asideContent') myAside: ElementRef;
  constructor(
    public request: RequestService,
    // 申明
    public http: HttpClient,
    public header: HttpHeaders
  ) { }
  ngOnInit(): void {}

  httpRequest() {
    const header = {
      headers: new HttpHeaders({'Content-Type': 'application/json'})
    }
    // jsonp请求后台必须支持jsonp请求
    this.http.jsonp('localhost:8080/test', 'callback').subscribe((res: any) => {
      console.log(res);
    });
  }
 }

使用第三方详情请见:https://blog.csdn.net/weixin_42603009/article/details/91477222

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值