angular9 Vs vue 个人总结

ng Vs vue

当前angular已经出到10了。

默认已有扎实的vue功底

循环体的根元素

template ng-container

<ng-container *ngIf="lessons">
    <div class="lesson" *ngFor="let lesson of lessons">
        <div class="lesson-detail">
            {{lesson | json}}
        </div>
    </div>
</ng-container>

插槽1

slot ngTemplateOutlet

<ng-container *ngTemplateOutlet="aaa; context: {{$implicit: '我是默认值,隐式定义,不需要赋值,对应let-name', diyValue: '我是自定义对象,需要赋值'}}" ></ng-container>

<ng-template #aaa let-name let-diyValue=”diyValue“>
	默认值- {{name}}
    赋值- {{diyValue}}
</ng-template>

#aaa叫做模板引用变量
let-name叫做模板输入变量
这里的理解是,

ng-template插入对应的ng-container的引用标记中,

#aaa插入到对应的*ngTemplateOutlet="aaa"

然后将变量``传入模板内,模板内接受变量进行赋值let-diyValue="xx",`

完了在模板作用域内使用该变量{{diyValue}}`

自定义组件

引用

<ng-container *ngFor="let item of [1,2,3]; let idx=index">
    <app-template-test [dTemplate]="tpl">
      <ng-template #tpl>
        <div>
          <p>我进来看看{{item}}</p>
          <p>我也进来康康{{idx}}</p>
        </div>
      </ng-template>
    </app-template-test>
  </ng-container>

ts

import { Component, OnInit, Input, TemplateRef } from '@angular/core';

@Component({
  selector: 'app-template-test',
  templateUrl: './template-test.component.html',
  styleUrls: ['./template-test.component.css']
})
export class TemplateTestComponent implements OnInit {
  @Input() dTemplate: TemplateRef<void>; // 接受外部模板
  
  constructor() { }

  ngOnInit(): void {
  }

}

html

<div>
  自己写的组件
  blablabla
  <ng-template #defaultContent>
    我是默认显示的内容
  </ng-template>
  // 使用外部模板或者使用自定义模板
  <ng-template [ngTemplateOutlet]="dTemplate || defaultContent"></ng-template>
</div>

组件传值

父传子

方法一 在父组件上设置子组件的属性【类似vue的props传参】
父组件绑定信息

<app-child childTitle="可设置子组件标题"></app-child>

子组件接收消息

import { Component, OnInit, Input } from '@angular/core';
@Input childTitle: string; // 类似vue的props接收参数

方法二 父组件调用子组件的方法
父组件触发消息 【类似vue的ref.methods的写法,区别是直接在模板调用】

<app-child #child></app-child> <button (click)="child.childPrint()"></button>

子组件接收消息

childPrint() {
  alert("来自子组件的打印");
}

子传父

子组件向父组件传递信息
方法一 使用 EventEmitter
子组件使用 EventEmitter 传递消息

【类似vue的this. e m i t ( m e t h o d s N a m e , d a t a ) , < d i v @ m e t h o d s N a m e = " p a r e n t M e t h o d ( emit(methodsName, data), `<div @methodsName="parentMethod( event)">点我`】

import { Component, OnInit, Output, EventEmitter } from '@angular/core';
...
@Output() initEmit = new EventEmitter<string>();
ngOnInit() {
  this.initEmit.emit("子组件初始化成功");
}
...

父组件接收消息

<app-child (initEmit)="accept($event)"></app-child>
accept(msg:string) {
  alert(msg);
} 

方法二 使用 ViewChild
子组件提供传递参数的函数 【类似vue的ref操作,调用子组件方法来传数据】

sendInfo() {
  return 'Message from child 1.';
}
// 父组件使用 ViewChild 触发并接收信息
<button (click)="getInfo()">获取子组件1号的信息</button>
import { Component, OnInit, ViewChild } from '@angular/core';
...
@ViewChild(ChildFirstComponent) private childcomponent: ChildFirstComponent;
getInfo() {
  this.info = this.childcomponent.sendInfo();
}

非父子组件通信

方法一:server

缺点:需要双向的触发(发送信息 / 接收信息)

service.ts 一个公共的state文件

import { Component, Injectable, EventEmitter } from "@angular/core";
@Injectable() // 可注入的服务
export class myService {
  public info: string = ""; // 相对于vue的state
  constructor() {}
}

组件 1 向 service 传递信息

import { myService } from '../../service/myService.service'; // 在组件中引入服务
...
constructor(
  public service: myService // 实例化服务
) { }

changeInfo() {
  this.service.info = this.service.info + "1234"; // 修改服务
}
...

组件 2 从 service 获取信息

import { myService } from '../../service/myService.service';
...
constructor(
  public service: myService
) { }

showInfo() {
  alert(this.service.info);
}
...

方法二: 使用 BehaviorSubject

优点:真正的发布订阅模式,当数据改变时,订阅者也能得到响应

service

import { BehaviorSubject } from 'rxjs';
...
public messageSource = new BehaviorSubject<string>('Start');
changemessage(message: string): void {
  this.messageSource.next(message);
}

组件调用 service 的方法传信息和接收信息

changeInfo() {
  this.communication.changemessage('Message from child 1.');
}
ngOnInit() {
  this.communication.messageSource.subscribe(Message => {
    window.alert(Message);
    this.info = Message;
  });
}

其他的通信方式

  • 路由传值
  • cookie、session、storage
  • 类vuex的东东…

内容投影(插槽2

ng-content 【类似vue的slot】

语法:

<ng-content select=".class,#id,select">

ng-content提供占位,select属性选择站位元素,相对于slot的名字。

创建组件

ng g c content-part-layout

ng g c content-part-a

ng g c content-part-b

content-part-layout

<p>content-part-layout works!</p>
<div>
  <div>主页面</div>
  <app-content-part-a></app-content-part-a>
  <app-content-part-b></app-content-part-b>
  <div> a嵌套b </div>
  <app-content-part-a>
    <div class="mydiv">我是a页面</div>
    <app-content-part-b></app-content-part-b>
  </app-content-part-a>
</div>

content-part-a

<p>content-part-a works!</p>
<ng-content select=".mydiv"></ng-content>
<ng-content select="app-content-part-b"></ng-content>

app.component.html

<!-- 内容投影,组件嵌套 -->
<app-content-part-layout></app-content-part-layout>
 <div class="mydiv">我是a页面</div>
 <app-content-part-b></app-content-part-b>

上面这段代码会带入到content-part-a里面对应的select选择名所在的ng-content位置

生命周期

ngOnInit()钩子

使用 ngOnInit() 有下面两个原因:

  1. 在构造函数之后马上执行复杂的初始化逻辑;

  2. 在 angular 设置完输入属性后,马上对该组件进行准备;

    它是获取初始化数据的好时期,不过要注意,是在 constructor 之后,因为在这之前,绑定的输入属性还没有值,这时候没有初始化,当OnInit 执行的时候,那些属性都已经被正确的赋值过了。

ngOnChange()钩子

类似vue的watch

当检测到组件的输入属性即 Input 进来的属性发生了变化的时候,就会调用它的 ngOnChange() 钩子;

ngOnChanges(changes: SimpleChanges) {
  for (let propName in changes) {
    let chng = changes[propName];
    let cur  = JSON.stringify(chng.currentValue);
    let prev = JSON.stringify(chng.previousValue);
    this.changeLog.push(`${propName}: currentValue = ${cur}, previousValue = ${prev}`);
  }
}
ngDoCheck

用来捕获那些 angular 自身们无法检测的变更,从而作出某些操作;但是这个可能导致一点小变换就被触发一次,严重浪费性能,不建议使用;

ngAfterContentInit

把内容投影进组件后调用

ngAfterContentChecked

完成被投影组件的变更检测后调用

ngAfterViewInit

我们可以通过 viewChild 来让组件访问子组件的属性; 当子组件视图初始化的时候,viewChild 被设置

ngAfterViewChecked

当子组件的视图checked 之后,viewChid 被更新;这个也很容易被触发,从而产生性能问题,需要尽量将操作写得简单

ngOnDestroy() 钩子

释放那些不会被垃圾收集器自动回收的各类资源的地方, 可以避免内存泄露

  • 取消那些对可观察对象和 DOM 事件的订阅

  • 停止定时器

  • 注销该指令曾注册到全局服务或应用级服务中的各种回调函数。

概念

核心是组件

  • 组件里有两大要素,

    • 其一是模板,与用户直接交互;
    • 另一要素是组件类,用以维护组件的数据模型功能逻辑
  • 模板是通过元数据指定的,元数据还包括其他重要的信息,这些信息是告诉Angular如何去解释一个普通的类,元数据结合普通类而形成组件

  • 指令是 Angular 里的独立构成,他与模板密切关联,用来增强模板特性,间接扩展了模板的语法

  • 服务也是 Angular 里的独立构成,他是封装单一功能逻辑的单元,它定义了一些实例函数,提供了一些特定功能,通常为组件提供功能扩展

  • 服务要能为组件所使用,是通过“依赖注入”机制把服务引入到组件内部,

    服务既可以单独注入到某一组件,亦可注入到模块,两种注入方式使得服务的作用域不一样;

    服务在引入之前会有一个实例化的过程,这个实例需要缓存,

    而管理实例化和缓存实例就是“依赖注入机制”实现的;

模块

模块把组件、指令和管道打包成内聚的功能块,

每个模块聚焦于一个特性区域、业务领域、工作流或通用工具。

模块还可以把服务加到应用中。

这些服务可能是内部开发的(比如你自己写的),或者来自外部的(比如 Angular 的路由和 HTTP 客户端)。

模块可以在应用启动时立即加载,也可以由路由器进行异步的惰性加载。

特性模块

特性模块的构造和根模块一样,它提供了特定应用需求的一组功能,如用户工作流、路由或表单。

虽然也可以用根模块做这些,但是特性模块可以帮助你把应用划分成一些聚焦的功能区。

特性模块通过它提供的服务以及共享出的组件、指令和管道来与根模块和其它模块合作。

主要理解里面的模块用法和组件用法,这对于共用模块,公共组件的封装有很大的帮助。

猜你喜欢

转载自blog.csdn.net/junjiahuang/article/details/108235571