zoukankan      html  css  js  c++  java
  • angular7学习笔记

    安装angular的命令行工具

    npm i -g @angular/cli

    安装完后执行以下命令创建新项目:

    ng new 项目名

    然后进入项目目录

    cd 项目名

    启动开发环境

    ng server

    快速创建组件(并自动在app.module.ts中导入)

    ng g c 组件名

    属性绑定

    [属性名]="表达式"

    如果不加[] 那""里面的就会被当前字符串

    如[bgColor]="'red'"等同于 bgColor="red"

    如果[bgColor]="red" 这样写, 那编译器会找不到red这个变量

    class绑定

    [ngClass]="{xxx: 表达式, ... }" 表达式为真则元素就有xxx这个class

    style绑定

    注意css属性名是驼峰式

    [ngStyle]="{backgroundColor: isRed ? 'red' : 'green'}"

    条件渲染

    *ngIf="表达式" 

    *ngIf="表达式; else 元素引用名称"

    <xxx #名称 >

    <div [ngSwitch]="...">
        <div *ngSwitchCase="...">
        </div>
    </div>

    循环渲染

    *ngFor="let item of list"

    注意:同一个元素只能有一个*指令

    服务类组件

    用于封装可复用的业务逻辑代码

    一般命名为 xxx.service.ts

    创建服务:

    import { Injectable } from '@angular/core';
    
    @Injectable()
    export class HelloService {
        printHello(): void {
            console.log('hello');
        }
    }

    在app.module.ts中注册一个provider:

    //引入HelloService 
    import {HelloService} from './hello.service';
    //在构造函数中进行依赖注入
    @NgModule({
        ...
        providers: [HelloService],
        ...
    })

    在需要用到的页面引入该服务:

    import {HelloService} from './hello.service';
    
    //在构造函数中进行依赖注入
    constructor(private helloService: HelloService) {...}
    
    //调用服务组件的方法
    this.helloService.printHello();
    • 服务都是单例的,一旦创建就会被缓存起来 重复使用
    • 服务一旦实例化,将在整个应用的生命周期中存在,可以用来共享数据(下面axios部分有实例)
    • 在需要使用服务的地方,利用依赖注入机制注入服务
    • 依赖注入时自定义的服务需要写在内置的服务后面

    父组件 向 子组件 传数据

    <sub-component [propName]="value" >

    绑定事件监听

    <div (click)="myFunction($event)" >

    在组件ts文件内定义myFunction方法,其可接收到$event事件对象

    自定义事件

    <sub-component (myEvent)="doSomething()">

    在子组件中,引入EventEmitter,

    import {EventEmitter} from "@angular/core";

    子组件先声明事件对象

    @Output() myEvent = new EventEmitter<boolean>();

    子组件的某个方法里调用

    this.myEvent.emit(agreed);


    解决跨级组件通信

    1 创建服务,new一个EventEmitter

    import {Injectable, EventEmitter, OnInit} from "@angular/core";
    @Injectable()
    export class EmitService implements OnInit {
        public eventEmit: any;
    
        constructor() {
            // 定义发射事件
            this.eventEmit = new EventEmitter();
        }
    
        ngOnInit() {
    
        }
    }

    2、配置module.ts

    import {BrowserModule} from '@angular/platform-browser';
    import {NgModule} from '@angular/core';
    
    import {AppComponent} from './app.component';
    import {EmitComponent} from "./emit.component";
    import {EmitService} from "./emit.service";
    
    @NgModule({
        declarations: [
            AppComponent,
            EmitComponent
        ],
        imports: [
            BrowserModule
        ],
        providers: [
            EmitService
        ],
        bootstrap: [
            AppComponent
        ]
    })
    export class AppModule {
    }

    3、定义组件,发射消息

    import {Component} from '@angular/core';
    import {EmitService} from "./emit.service"
    @Component({
        selector: 'app-root',
        templateUrl: './app.component.html',
        styleUrls: ['./app.component.css']
    })
    export class AppComponent {
        constructor(public emitService: EmitService) {
    
        }
    
        emitFun() {
            // 如果组件中,修改了某些数据,需要刷新用用户列表,用户列表在其他组件中,那么就可以发射一个字符串过去,那边接收到这个字符串比对一下,刷新列表。
            this.emitService.eventEmit.emit("userList");
        }
    }

    4、定义接收组件,接收比对发射的字符串,判断,调取接口,刷新组件内容

    import {Component, OnInit} from "@angular/core";
    import {EmitService} from "./emit.service"
    @Component({
        selector: "event-emit",
        templateUrl: "./emit.component.html"
    })
    export class EmitComonent implements OnInit {
        constructor(public emitService: EmitService) {
    
        }
    
        ngOnInit() {
            // 接收发射过来的数据
            this.emitService.eventEmit.subscribe((value: any) => {
               if(value == "userList") {
                   // 这里就可以调取接口,刷新userList列表数据
                   alert("收到了,我立马刷新列表");
               }
            });
        }
    
    }

    总结:其实就是EventEmitter的两个方法,emit(),subscribe()发射和接收;

     

    对象本地指向

    (如果是input元素,其类型是HTMLInputElemet)

    <div #oneElement > 
    <div (click)="func(oneElement)" >
    import {ElementRef, ViewChild, ContentChild} from 'angular/core';
    
    //通过 @ViewChild 引用 当前组件模板中的#名称的dom元素 
    @ViewChild('名称') 变量名: ElementRef
    
    //通过 @ContentChild 引用 父组件中子组件的子元素#名称的dom元素
    @ContentChild('名称') 变量名: ElementRef

    内容分发(类似Vue的slot)

    子组件利用<ng-content></ng-content> 引用 父组件中此组件标签的子元素.

    生命周期

    init之前会调constructor()

    ngOnChanges(change: SimpleChanges) ;需要import {SimpleChanges } from '@angular/core';

    ngOnInit

    ngDoCheck

    ngAfterContentInit

    ngAfterContentChecked

    ngAfterViewInit

    ngAfterViewChecked

    ngOnDestroy

    class xxx implements OnInit, OnChanges

    自定义指令

    @Directive({
            selector: '[指令名]'
    })
    export class 类名 implements OnInit {
        constructor(private elementRef: ElementRef, renderer: Renderer2) {
             
        }
        ngOnInit() {
        this.renderer.setStyle(this.elementRef.nativeElement, 'background-color', 'red');
      } }

    构造函数的参数elementRef就是调用这个指令的元素,前面应该加上private,否则在类中其它方法中引用this.el时会报错

    调用时就是在元素中用上面的指令名做为属性名, 不需要加[]或*, 

    使用之前还要在ngModule的declarations中声明(官方文档里居然没有写这部分)

    @ngModule({
        declarations: {
            指令类名
        }
    })

    我用ionic g d 指令名 这个命令生成的指令, 它自动生成了"directives"文件夹,其下生成了 directives.module.ts 和 "指令名/指令名.directive.ts", directives.module.ts 内容如下:

    import { NgModule } from '@angular/core';
    import { HightLightDirective } from './hight-light/hight-light';
    @NgModule({
        declarations: [HightLightDirective],
        imports: [],
        exports: [HightLightDirective]
    })
    export class DirectivesModule {}

    同时,如果使用 directives.module.ts , 那么,在app.module.ts中也可以这样引用并声明指令:

    import { DirectivesModule } from '../directives/directives.module';
    
    @NgModule({
        ...
        //导入 模块
        imports: [
            DirectivesModule,
            ...
        ],
        ...
    })

    用命令行工具创建指令

    ng g d 路径/my-name

    指令文件名小写以-连接,生成文件名为my-name.directive.ts,

    生成的指令类名为MyNameDirectvie, 选择器名为appMyName,

    在指令类中,通过@hostlistener监听事件

    import {HostListener} from '@angular/core';
    @HostListener('mouseenter') dosomething(event: Event) {}

    在指令类中,通过@HostBinding绑定属性,将指令内的变量绑定到引用元素上的属性值

    import {HostBinding} from '@angular/core';
    @HostBinding('style.backgroundColor') bgc:strind = 'red';

    还可以通过引用元素的属性向指令传递参数,方法与经组件传参数一样,用@input()

    路由

    1.在app-routing.module.ts中引用路由模块

    (*以下代码,在使用ng new 创建项目时如果选择了使用路由,那么将会自动创建)

    import { NgModule } from '@angular/core';
    import { Routes, RouterModule } from '@angular/router';
    
    const routes: Routes = [];
    
    @NgModule({
      imports: [RouterModule.forRoot(routes)],
      exports: [RouterModule]
    })
    export class AppRoutingModule { }

    2.引入组件

    在根模块中引入和声明组件, (如果是通过命令创建的组件,则工具会自动完成这步)

    在app-routing.module.ts中引入组件

    import { MyComponent } from "path/to/MyComponent";

    3.定义路由规则

    const routes: Routes = [
        {path: 'path1', component: MyComponent1},
        {path: 'path2', component: MyComponent2},
        ....
    ];

    path如果以/开头就是绝对路径,指向网站根路径,即http://domain/, 否则就是相对路径,相对于当前 定义路由的模块的路径.

    比如在 app-routing.module.ts 中定义了一条path: news, 访问时就是 http://domain/news

    *在浏览器中访问时路径区分大小写

    在根组件模板中添加"路由出口",即在HTML中路由动态加载组件的地方

    <router-outlet></router-outlet>

    默认路由

      {path: '**', component: HomeComponent}

      {path: '**', redirectTo: 'home'}

    '**'表示匹配任意路径,(实测发现 '' 也可以)

    注意,这个默认路由规则 必须 写在后面,如果写在前面,那其它规则就都失效了

    创建跳转链接, 在一个标签中使用

    [routerLink]="[ '/news' ]"

    路径如果是相对路径,则是相对当前的url,

    当前激活路由,给他一个类用来指定激活路由的样式

    routerLinkActive="active"

    路由传参

    get方式

    //在html中跳转连接上加上
    [queryParams]="{id:123}"
    
    //跳转的目标组件引入
    import { ActivatedRoute } from '@angular/router';
    
    //目标组件声明
    constructor(public route: ActivatedRoute) {}

    //接收参数
    this.route.queryParams.subscribe((data)=>{   
    console.log(data);
    // {id: 123}
    })

    动态路由

    //定义路由规则 , 只要在path的值中加入:参数名就可以了
    {path: 'home/:id', component: HomeComponent}
    
    //定义连接
    [routerLink]="['/path/',  id]"
    
    //目标组件中仍然要引入ActivatedRoute
    import {ActivatedRoute} from '@angular/router';
    
    //在构造函数中声明
    constructor(public route: ActivatedRoute) {}
    
    //接收参数,与get传参唯一不同的是.params
    this.route.params.subscribe((data) => {
        console.log(data); //{id: xxx}
    });

    //官方文档中是这样写的: (paramMap和params有什么区别?)
    this.route.paramMap.subscribe(params => {
    this.product = products[+params.get('productId')];
    });

    编程方式路由跳转

    在JS代码中用路由的API进行跳转, 上面的跳转都是通过html中添加[routerLink]属性

    编程路由跳转也分为GET传值和 动态路由 两种方式

    编程式动态路由跳转:

    //同样需要在路由规则中配置动态路由规则
    {path: 'home/:id', component: HomeComponent}
    
    //在要调用路由跳转API的组件中引入路由模块
    import {Router} from '@angular/router';
    
    //在构造函数上声明
    contructor(public router: Router) {}
    
    //调用, navigate的第一个参数是一个数组
    this.router.navigate(['/path', param]);
    
    //接收
    this.route.params.subscribe((data) => {
        console.log('在news页中接收到',data); // {id: 123}
    })

    编程式GET传参路由跳转

    //引入
    import { Router, NavigationExtras } from '@angular/router';
    
    
    //定义路由参数
    let navigationExtras: NavigationExtras = {
        queryParams: {id: 123},
        fragment: 'anchor'
    }
    this.router.navigate(['/path'], navigationExtras);
    
    //接收
    this.route.queryParams.subscribe((data) => {
        console.log('在news页中接收到',data); // {id: 123}
    });

    父子路由/嵌套路由

    //在路由规则中定义子中由
    const routes: Routes = [
      {
            path: '...',component: ...,
            children: [
        {path: ..., component: ...},
        ...
            ]
        },
    ]
    //跳转
    <a [routerLink]="['/path/to']"  ></a>
    //或
    <a [routerLink]="['to']"  ></a>
    //在父组件中加入 组件模板出口
    <router-outlet></router-outlet>

    HTTP数据请求

    GET请求

    1.在app.module.ts引入HttpClientModule .

    import {HttpClientModule} from '@aunglar/common/http';
    imports: [..., HttpClientModule, ...]

    2.在用到的地方引入

    import {HttpClient} from '@angular/common/http';
    并在构造函数声明
    constructor(public http: HttpClient) {}

    3.使用get请求数据

    this.http.get(url).subscribe((response)=>{});

    POST请求

    1.在app.module.ts引入HttpClientModule .与上面一样(略)

    2.在用到的地方引入

    import {HttpClient, HttpHeaders} from '@angular/common/http';

    3.定义http请求选项

    const httpOptions = {
        headers: new HttpHeaders({'Content-Type', 'application/json'});
    };    

    4.调用post请求

    this.http.post(url, {...}, httpOptions).subscribe((response)=>{});

    JSONP请求

    1.在app.module.ts引入HttpClientModule 和 HttpClientJsonpModule 

    import { HttpClientModule, HttpClientJsonpModule } from '@aunglar/common/http';
    imports: [..., HttpClientModule, HttpClientJsonpModule, ...]

     2.在用到的地方引用HttpClientModule,(同get请求,略)

    并在构造函数声明

    3.使用get请求数据

    this.http.jsonp(url, 'callback').subscribe((response)=>{});

    注: 第二个参数根据实际服务器的情况设置,可以通过在浏览器地址栏直接访问接口地址,观察返回结果,如果开头是callback就写callback,是什么第二个参数就写什么

    另:http也提供了put,delete 方法

    使用axios请求数据

    安装

    npm i axios -S

    可以新建一个服务, 如果不用服务封装,也可以直接在使用的组件中直接引入axios并使用

    ng g service service/http

    在其中引入

    import axios from 'axios';

    调用

    axiosGet(url) {
    return new Promise((resolve, reject)=>{
        axios.get(url).then((response)
    =>{      resolve(response);    });
    });
    }

    在app.module.ts中引入服务

    import httpService from './service/httpservice.service';

    并在providers中声明

    providers: [..., httpService, ...]

    在使用服务的文件中也要引入服务 (略)

    在构造函数的参数中声明服务对象

    constructor(...,public httpService: HttpService) {}

    调用

    this.httpService.axiosGet(url).then(...)
    喜欢的话,请点赞,转发、收藏、评论,谢谢!
  • 相关阅读:
    [RxSwift]3.3、数据绑定(订阅)
    [RxSwift]3.2、函数式编程 -> 函数响应式编程
    [RxSwift]2、Hello RxSwift!:我的第一个 RxSwift 应用程序
    [RxSwift]1、为什么要使用 RxSwift ?
    [RxSwift]RxSwift: ReactiveX for Swift
    [Swift]UIViewController
    104. 二叉树的最大深度
    103. 二叉树的锯齿形层次遍历
    102. 二叉树的层序遍历
    98. 验证二叉搜索树
  • 原文地址:https://www.cnblogs.com/johnjackson/p/11027212.html
Copyright © 2011-2022 走看看