>웹 프론트엔드 >JS 튜토리얼 >Angular Component의 소스 코드 예제 분석

Angular Component의 소스 코드 예제 분석

亚连
亚连원래의
2018-05-26 15:43:521275검색

이 글에서는 주로 Angular Component를 분석하는 소스 코드 예제를 소개하고 참고 자료를 제공합니다.

Web Component

Angular Component를 소개하기에 앞서 W3C Web Components

Definition

W3C는 통일된 Component 표준 방식으로 Web Component의 표준을 제안하는 것에 대해 간단히 알아보겠습니다.

각 구성 요소에는 고유한 html, css 및 js 코드가 포함되어 있습니다.
웹 구성 요소 표준에는 다음과 같은 네 가지 중요한 개념이 포함됩니다.
1.사용자 정의 요소(사용자 정의 태그): 사용자 정의 HTML 태그 및 요소를 생성할 수 있습니다.
2.HTML 템플릿(HTML 템플릿): d477f9ce7bf77f53fbcf36bec1b69b7a 일부 콘텐츠를 정의하되 페이지에 로드하지 말고 JS 코드를 사용하여 초기화하세요.
3. Shadow DOM(가상 DOM): 다른 요소와 완전히 독립적인 DOM 하위 트리를 만들 수 있습니다. (HTML Imports ): HTML 문서에 다른 HTML 문서를 도입하는 방법, 01a3a061c487227e31d0b850a8271aa1.

요약하자면, 구성 요소를 도입하기 위해 사용자 정의 태그를 생성하는 기능은 프런트 엔드 구성 요소화의 기초입니다. 페이지의 HTML 파일 및 HTML 템플릿에 대한 참조는 구성 요소 뷰 작성 및 구성 요소 리소스 관리를 지원하는 데 사용되며 Shadow DOM은 사용됩니다. 코드 충돌 및 영향을 격리합니다.

Example

Define hello-comComponent

<template id="hello-template">
  <style>
    h1 {
      color: red;
    }
  </style>
  <h1>Hello Web Component!</h1>
</template>

<script>

  // 指向导入文档,即本例的index.html
  var indexDoc = document;

  // 指向被导入文档,即当前文档hello.html
  var helloDoc = (indexDoc._currentScript || indexDoc.currentScript).ownerDocument;

  // 获得上面的模板
  var tmpl = helloDoc.querySelector(&#39;#hello-template&#39;);

  // 创建一个新元素的原型,继承自HTMLElement
  var HelloProto = Object.create(HTMLElement.prototype);

  // 设置 Shadow DOM 并将模板的内容克隆进去
  HelloProto.createdCallback = function() {
    var root = this.createShadowRoot();
    root.appendChild(indexDoc.importNode(tmpl.content, true));
  };

  // 注册新元素
  var hello = indexDoc.registerElement(&#39;hello-component&#39;, {
    prototype: HelloProto
  });
</script>

Use hello-comComponent

<!DOCTYPE html>
<html lang="zh-cn">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-COMPATIBLE" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <meta name="author" content="赖祥燃, laixiangran@163.com, http://www.laixiangran.cn"/>
  <title>Web Component</title>
  <!--导入自定义组件-->
  <link rel="import" href="hello.html" rel="external nofollow" >
</head>
<body>
  <!--自定义标签-->
  <hello-component></hello-component>
</body>
</html>

위 코드에서 볼 수 있듯이 hello.html은 표준에 의해 정의된 컴포넌트( hello-컴포넌트) 이 컴포넌트는 고유한 구조와 스타일, 로직을 갖고 있으며 index.html에 컴포넌트 파일을 도입하여 일반 태그처럼 사용할 수 있습니다.

Angular Component

Angular Component는 지시어의 일종으로 템플릿이 있는 지시어로 이해될 수 있습니다. 다른 두 가지 유형은 속성 지시문과 구조 지시문입니다.

기본 구성


@Component({
  selector: &#39;demo-component&#39;,
  template: &#39;Demo Component&#39;
})
export class DemoComponent {}

  1. 컴포넌트 데코레이터: 각 컴포넌트 클래스는 @comComponent로 데코레이션되어야 Angular 컴포넌트가 됩니다.

  2. 컴포넌트 메타데이터: 컴포넌트 메타데이터: 선택기, 템플릿 등 다음은 각 메타데이터의 의미에 중점을 둡니다.

  3. 컴포넌트 클래스: 컴포넌트는 실제로는 일반적인 클래스이며 컴포넌트의 로직은 컴포넌트 클래스에서 정의되고 구현됩니다.

  4. 구성 요소 템플릿: 각 구성 요소는 결국 페이지에 렌더링되는 템플릿과 연결됩니다. 페이지의 DOM 요소는 이 구성 요소 인스턴스의 호스트 요소입니다.

구성 요소 메타데이터

자체 메타데이터 속성


NameTypeFunctionanimationsAnimationEntry 메타데이터[]구성요소의 애니메이션 설정changeDetectionChangeDetectionStrategy구성 요소의 변경 감지 전략 설정encapsulationViewEncapsulation구성 요소의 뷰 패키징 옵션 설정entryComponentsany[] 설정은 구성요소 보기에 동적으로 삽입됩니다. 컴포넌트 목록interpolation[string, string]커스텀 컴포넌트의 보간 표시, 기본값은 이중 중괄호moduleIdstringES 아래에 컴포넌트의 모듈을 설정합니다. /CommonJS 사양 ID, 템플릿 스타일의 상대 경로를 확인하는 데 사용됨styleUrlsstring[]구성 요소에서 참조하는 외부 스타일 파일 설정stylesstring[]Set 구성 요소에서 사용하는 인라인 스타일 templatestring구성 요소의 인라인 템플릿 설정templateUrlstring구성 요소 템플릿이 있는 경로 설정viewProviders Provider[]구성 요소 및 모든 하위 구성 요소 설정(ContentChildren 제외) 사용 가능한 서비스
코어/지시문에서 상속됨 ​​


NameTypeFunctionexportAs string템플릿에 구성 요소 인스턴스 설정 별칭 in을 사용하면 host{[key: string]: string}을 호출하여 구성 요소의 이벤트, 작업 및 속성을 설정할 수 있습니다inputsstring[]settings 구성 요소의 입력 속성outputsstring[]구성 요소의 출력 속성 설정providersProvider[]Set 는 구성 요소 및 모든 하위 구성 요소(ContentChildren 포함)에 사용할 수 있는 서비스(종속성 주입) )queries{[key: string]: any}구성 요소에 주입해야 하는 쿼리를 설정합니다selectorstring템플릿에서 이 구성 요소를 식별하는 데 사용되는 CSS 선택기를 설정합니다(구성 요소에 대한 사용자 정의 태그)

几种元数据详解

以下几种元数据的等价写法会比元数据设置更简洁易懂,所以一般推荐的是等价写法。

inputs

@Component({
  selector: &#39;demo-component&#39;,
  inputs: [&#39;param&#39;]
})
export class DemoComponent {
  param: any;
}

等价于:

@Component({
  selector: &#39;demo-component&#39;
})
export class DemoComponent {
  @Input() param: any;
}

outputs

@Component({
  selector: &#39;demo-component&#39;,
  outputs: [&#39;ready&#39;]
})
export class DemoComponent {
  ready = new eventEmitter<false>();
}

等价于:

@Component({
  selector: &#39;demo-component&#39;
})
export class DemoComponent {
  @Output() ready = new eventEmitter<false>();
}

host

@Component({
  selector: &#39;demo-component&#39;,
  host: {
    &#39;(click)&#39;: &#39;onClick($event.target)&#39;, // 事件
    &#39;role&#39;: &#39;nav&#39;, // 属性
    &#39;[class.pressed]&#39;: &#39;isPressed&#39;, // 类
  }
})
export class DemoComponent {
  isPressed: boolean = true;

  onClick(elem: HTMLElement) {
    console.log(elem);
  }
}

等价于:

@Component({
  selector: &#39;demo-component&#39;
})
export class DemoComponent {
  @HostBinding(&#39;attr.role&#39;) role = &#39;nav&#39;;
  @HostBinding(&#39;class.pressed&#39;) isPressed: boolean = true;

 
  @HostListener(&#39;click&#39;, [&#39;$event.target&#39;])
  onClick(elem: HTMLElement) {
    console.log(elem);
  }
}

queries - 视图查询

@Component({
  selector: &#39;demo-component&#39;,
  template: `
    <input #theInput type=&#39;text&#39; />
    <p>Demo Component</p>
  `,
  queries: {
    theInput: new ViewChild(&#39;theInput&#39;)
  }
})
export class DemoComponent {
  theInput: ElementRef;
}

等价于:

@Component({
  selector: &#39;demo-component&#39;,
  template: `
    <input #theInput type=&#39;text&#39; />
    <p>Demo Component</p>
  `
})
export class DemoComponent {
  @ViewChild(&#39;theInput&#39;) theInput: ElementRef;
}

queries - 内容查询

<my-list>
  <li *ngFor="let item of items;">{{item}}</li>
</my-list>

@Directive({
  selector: &#39;li&#39;
})
export class ListItem {}

@Component({
  selector: &#39;my-list&#39;,
  template: `
    <ul>
      <ng-content></ng-content>
    </ul>
  `,
  queries: {
    items: new ContentChild(ListItem)
  }
})
export class MyListComponent {
  items: QueryList<ListItem>;
}

等价于:

@Component({
  selector: &#39;my-list&#39;,
  template: `
    <ul>
      <ng-content></ng-content>
    </ul>
  `
})
export class MyListComponent {
  @ContentChild(ListItem) items: QueryList<ListItem>;
}

styleUrls、styles

styleUrls和styles允许同时指定。

优先级:模板内联样式 > styleUrls > styles。

建议:使用styleUrls引用外部样式表文件,这样代码结构相比styles更清晰、更易于管理。同理,模板推荐使用templateUrl引用模板文件。

changeDetection

ChangeDetectionStrategy.Default:组件的每次变化监测都会检查其内部的所有数据(引用对象也会深度遍历),以此得到前后的数据变化。

ChangeDetectionStrategy.OnPush:组件的变化监测只检查输入属性(即@Input修饰的变量)的值是否发生变化,当这个值为引用类型(Object,Array等)时,则只对比该值的引用。

显然,OnPush策略相比Default降低了变化监测的复杂度,很好地提升了变化监测的性能。如果组件的更新只依赖输入属性的值,那么在该组件上使用OnPush策略是一个很好的选择。

encapsulation

ViewEncapsulation.None:无 Shadow DOM,并且也无样式包装。

ViewEncapsulation.Emulated:无 Shadow DOM,但是通过Angular提供的样式包装机制来模拟组件的独立性,使得组件的样式不受外部影响,这是Angular的默认设置。

ViewEncapsulation.Native:使用原生的 Shadow DOM 特性。

生命周期

当Angular使用构造函数新建组件后,就会按下面的顺序在特定时刻调用这些生命周期钩子方法:


生命周期钩子 调用时机
ngOnChanges 在ngOnInit之前调用,或者当组件输入数据(通过@Input装饰器显式指定的那些变量)变化时调用。
ngOnInit 第一次ngOnChanges之后调用。建议此时获取数据,不要在构造函数中获取。
ngDoCheck 每次变化监测发生时被调用。
ngAfterContentInit 使用
ngAfterContentChecked ngAfterContentInit后被调用,或者每次变化监测发生时被调用(只适用组件)。
ngAfterViewInit 创建了组件的视图及其子视图之后被调用(只适用组件)。
ngAfterViewChecked ngAfterViewInit,或者每次子组件变化监测时被调用(只适用组件)。
ngOnDestroy 销毁指令/组件之前触发。此时应将不会被垃圾回收器自动回收的资源(比如已订阅的观察者事件、绑定过的DOM事件、通过setTimeout或setInterval设置过的计时器等等)手动销毁掉。

上面是我整理给大家的,希望今后会对大家有帮助。

相关文章:

Ajax发送和接收二进制字节流数据的方法

laypage前端分页插件实现ajax异步分页

ajax文件上传成功 解决浏览器兼容问题

위 내용은 Angular Component의 소스 코드 예제 분석의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.