>  기사  >  웹 프론트엔드  >  Angular 구성요소와 상호작용하는 방법

Angular 구성요소와 상호작용하는 방법

php中世界最好的语言
php中世界最好的语言원래의
2018-06-14 10:06:241279검색

이번에는 Angular 컴포넌트를 사용하여 인터랙션하는 방법과 Angular 컴포넌트를 사용하여 인터랙션할 때 주의 사항이 무엇인지 보여드리겠습니다. 다음은 실제 사례입니다.

상위 구성 요소는 하위 구성 요소에 전달됩니다.

하위 구성 요소는 @Input 데코레이터를 통해 입력 속성을 정의한 다음 상위 구성 요소는 하위 구성 요소를 참조할 때 이러한 입력 속성을 통해 하위 구성 요소에 데이터를 전달합니다. 하위 구성 요소는 setter 또는 ngOnChanges()를 전달하여 입력 속성 값의 변경 사항을 가로챌 수 있습니다.

먼저 두 개의 구성 요소, 즉 하위 구성 요소인 DemoChildComponent와 상위 구성 요소인 DemoParentComponent를 정의합니다.

하위 구성 요소:

@Component({
 selector: 'demo-child',
 template: `
 <p>{{paramOne}}</p>
 <p>{{paramTwo}}</p>
 `
})
export class DemoChildComponent {
 @Input() paramOne: any; // 输入属性1
 @Input() paramTwo: any; // 输入属性2
}

하위 구성 요소는 @Input()을 통해 입력 속성 paramOne 및 paramTwo를 정의합니다. 모든 데이터 유형 가능)

상위 구성 요소:

@Component({
 selector: 'demo-parent',
 template: `
 <demo-child [paramOne]=&#39;paramOneVal&#39; [paramTwo]=&#39;paramTwoVal&#39;></demo-child>
 `
})
export class DemoParentComponent {
 paramOneVal: any = '传递给paramOne的数据';
 paramTwoVal: any = '传递给paramTwo的数据';
}

상위 구성 요소는 템플릿의 선택기 데모-child를 통해 하위 구성 요소인 DemoChildComponent를 참조하고, 두 가지 입력 속성 paramOne 및 paramTwo를 통해 하위 구성 요소에 데이터를 전달합니다. paramOne에 전달된 데이터와 paramTwo에 전달된 데이터는 두 줄의 텍스트입니다.

setter를 통한 입력 속성 값 변경 차단

실제 응용에서는 입력 속성 값이 변경되면 해당 연산을 수행해야 하는 경우가 많기 때문에 이때 입력의 setter를 사용해야 합니다. 입력 속성 값의 변경을 차단합니다.

하위 컴포넌트인 DemoChildComponent를 다음과 같이 변형했습니다.

@Component({
 selector: 'demo-child',
 template: `
 <p>{{paramOneVal}}</p>
 <p>{{paramTwo}}</p>
 `
})
export class DemoChildComponent {
 private paramOneVal: any;
 
 @Input() 
 set paramOne (val: any) { // 输入属性1
  this.paramOneVal = val;
  // dosomething
 };
 get paramOne () {
  return this.paramOneVal;
 };
 
 @Input() paramTwo: any; // 输入属性2
}

위 코드에서 가로챈 값 val이 paramOne 속성의 setter를 통해 내부 전용 속성인 paramOneVal에 할당되어 상위 컴포넌트가 통과하는 것을 볼 수 있습니다. 하위 구성 요소 효과에 대한 데이터입니다. 물론 가장 중요한 것은 setter에서 더 많은 다른 작업을 수행할 수 있어 프로그램이 더욱 유연해진다는 것입니다.

ngOnChanges()를 사용하여 입력 속성 값의 변경 사항을 가로채기

setter를 통해 입력 속성 값의 변경 사항을 가로채는 방법은 단일 속성 값의 변경 사항만 모니터링할 수 있습니다. 여러 개의 대화형 입력 속성을 모니터링해야 하는 경우입니다. 때로는 이 방법이 효과가 없을 때도 있습니다. OnChanges 라이프 사이클 후크 인터페이스(@Input 데코레이터를 통해 구성 요소에 의해 명시적으로 지정된 변수 값이 변경될 때 호출됨)의 ngOnChanges() 메서드를 사용하면 여러 입력 속성 값의 변경 사항을 동시에 모니터링할 수 있습니다.

하위 구성 요소 DemoChildComponent에 ngOnChanges를 추가하세요.

@Component({
 selector: 'demo-child',
 template: `
 <p>{{paramOneVal}}</p>
 <p>{{paramTwo}}</p>
 `
})
export class DemoChildComponent implements OnChanges {
 private paramOneVal: any;
 
 @Input() 
 set paramOne (val: any) { // 输入属性1
  this.paramOneVal = val;
  // dosomething
 };
 get paramOne () {
  return this.paramOneVal;
 };
 
 @Input() paramTwo: any; // 输入属性2
 
 ngOnChanges(changes: {[propKey: string]: SimpleChange}) {
  for (let propName in changes) { // 遍历changes
   let changedProp = changes[propName]; // propName是输入属性的变量名称
   let to = JSON.stringify(changedProp.currentValue); // 获取输入属性当前值
   if (changedProp.isFirstChange()) { // 判断输入属性是否首次变化
    console.log(`Initial value of ${propName} set to ${to}`);
   } else {
    let from = JSON.stringify(changedProp.previousValue); // 获取输入属性先前值
    console.log(`${propName} changed from ${from} to ${to}`);
   }
  }
 }
}

새 ngOnChanges 메서드에서 수신한 매개변수 변경 사항은 입력 속성 이름이 키이고 값이 SimpleChange인 개체입니다. SimpleChange 개체에는 현재 입력 속성이 변경되는지 여부가 포함됩니다. 처음 및 이전 값, 현재 값 및 기타 속성. 따라서 ngOnChanges 메소드에서는 여러 입력 속성 값을 모니터링하고 변경 객체를 순회하여 해당 작업을 수행할 수 있습니다.

상위 구성 요소 인스턴스 가져오기

이전 소개에서는 하위 구성 요소가 @Input 데코레이터를 통해 입력 속성을 정의하므로 상위 구성 요소가 입력 속성을 통해 하위 구성 요소에 데이터를 전달할 수 있다는 것이었습니다.

물론 상위 구성 요소 인스턴스를 얻은 다음 상위 구성 요소의 특정 속성이나 메서드를 호출하여 필요한 데이터를 얻는 보다 적극적인 방법을 생각할 수 있습니다. 각 컴포넌트 인스턴스가 인젝터의 컨테이너에 추가된다는 점을 고려하면, 종속성 주입을 통해 상위 컴포넌트의 인스턴스를 찾을 수 있습니다.

부모 구성 요소가 자식 구성 요소 인스턴스(템플릿 변수 @ViewChild 또는 @ViewChildren을 통해 직접 얻음)를 얻는 것보다 자식 구성 요소가 부모 구성 요소 인스턴스를 얻는 것이 더 번거롭습니다.

하위 구성 요소에서 상위 구성 요소의 인스턴스를 가져오려면 두 가지 상황이 있습니다.

상위 구성 요소의 유형이 알려져 있습니다.

이 경우 알려진 유형의 상위 구성 요소를 직접 가져올 수 있습니다. 생성자에 DemoParentComponent 삽입 인용하자면 코드 예제는 다음과 같습니다.

@Component({
 selector: 'demo-child',
 template: `
 <p>{{paramOne}}</p>
 <p>{{paramTwo}}</p>
 `
})
export class DemoChildComponent {
 paramOne: any;
 paramTwo: any;
 constructor(public demoParent: DemoParentComponent) {
  // 通过父组件实例demoParent获取数据
  this.paramOne = demoParent.paramOneVal;
  this.paramTwo = demoParent.paramTwoVal;
 }
}

알 수 없는 상위 구성 요소 유형

구성 요소는 여러 구성 요소의 하위 구성 요소일 수 있으며 때로는 상위 구성 요소의 유형을 직접 알 수 없습니다. Angular에서는 클래스 인터페이스(Class -Interface)를 사용할 수 있습니다. 즉, 클래스 인터페이스 식별자와 동일한 이름을 가진 별칭을 제공하여 상위 구성 요소가 검색을 지원하도록 할 수 있습니다.

먼저 구현(할당) 없이 paramOneVal 및 paramTwoVal 속성만 선언하는 DemoParent 추상 클래스를 만듭니다. 샘플 코드는 다음과 같습니다.

export abstract class DemoParent {
 paramOneVal: any;
 paramTwoVal: any;
}

그런 다음 상위 구성 요소 DemoParentComponent의 공급자 메타데이터에 별칭 공급자를 정의하고 사용합니다. 사용하여 상위 구성 요소 DemoParentComponent의 인스턴스를 삽입합니다. 코드 예제는 다음과 같습니다.

@Component({
 selector: 'demo-parent',
 template: `
 <demo-child [paramOne]=&#39;paramOneVal&#39; [paramTwo]=&#39;paramTwoVal&#39;></demo-child>
 `,
 providers: [{provider: DemoParent, useExisting: DemoParentComponent}]
})
export class DemoParentComponent implements DemoParent {
 paramOneVal: any = '传递给paramOne的数据';
 paramTwoVal: any = '传递给paramTwo的数据';
}

그런 다음 하위 구성 요소의 DemoParent 식별자를 통해 상위 구성 요소의 예제를 찾을 수 있습니다.

@Component({
 selector: 'demo-child',
 template: `
 <p>{{paramOne}}</p>
 <p>{{paramTwo}}</p>
 `
})
export class DemoChildComponent {
 paramOne: any;
 paramTwo: any;
 constructor(public demoParent: DemoParent) {
  // 通过父组件实例demoParent获取数据
  this.paramOne = demoParent.paramOneVal;
  this.paramTwo = demoParent.paramTwoVal;
 }
}

子组件向父组件传递

依然先定义两个组件,分别为子组件DemoChildComponent和父组件DemoParentComponent.

子组件:

@Component({
 selector: 'demo-child',
 template: `
 <p>子组件DemoChildComponent</p>
 `
})
export class DemoChildComponent implements OnInit {
 readyInfo: string = '子组件DemoChildComponent初始化完成!';
 @Output() ready: EventEmitter = new EventEmitter<any>(); // 输出属性
 
 ngOnInit() {
  this.ready.emit(this.readyInfo);
 }
}

父组件:

@Component({
 selector: 'demo-parent',
 template: `
 <demo-child (ready)="onReady($event)" #demoChild></demo-child>
 <p>
  <!-- 通过本地变量获取readyInfo属性,显示:子组件DemoChildComponent初始化完成! -->
  readyInfo: {{demoChild.readyInfo}}
 </p>
 <p>
  <!-- 通过组件类获取子组件示例,然后获取readyInfo属性,显示:子组件DemoChildComponent初始化完成! -->
  readyInfo: {{demoChildComponent.readyInfo}}
 </p>
 `
})
export class DemoParentComponent implements AfterViewInit {
 // @ViewChild('demoChild') demoChildComponent: DemoChildComponent; // 通过模板别名获取
 @ViewChild(DemoChildComponent) demoChildComponent: DemoChildComponent; // 通过组件类型获取
 
 ngAfterViewInit() {
  console.log(this.demoChildComponent.readyInfo); // 打印结果:子组件DemoChildComponent初始化完成!
 }
 onReady(evt: any) {
  console.log(evt); // 打印结果:子组件DemoChildComponent初始化完成!
 }
}

父组件监听子组件的事件

子组件暴露一个 EventEmitter 属性,当事件发生时,子组件利用该属性 emits(向上弹射)事件。父组件绑定到这个事件属性,并在事件发生时作出回应。

在上面定义好的子组件和父组件,我们可以看到:

子组件通过@Output()定义输出属性ready,然后在ngOnInit中利用ready属性的 emits(向上弹射)事件。

父组件在其模板中通过选择器demo-child引用子组件DemoChildComponent,并绑定了一个事件处理器(onReady()),用来响应子组件的事件($event)并打印出数据(onReady($event)中的$event是固定写法,框架(Angular)把事件参数(用 $event 表示)传给事件处理方法)。

父组件与子组件通过本地变量(模板变量)互动

父组件不能使用数据绑定来读取子组件的属性或调用子组件的方法。但可以在父组件模板里,新建一个本地变量来代表子组件,然后利用这个变量来读取子组件的属性和调用子组件的方法。

在上面定义好的子组件和父组件,我们可以看到:

父组件在模板demo-child标签上定义了一个demoChild本地变量,然后在模板中获取子组件的属性:

<p>
 <!-- 获取子组件的属性readyInfo,显示:子组件DemoChildComponent初始化完成! -->
 readyInfo: {{demoChild.readyInfo}}
</p>

父组件调用@ViewChild()

本地变量方法是个简单便利的方法。但是它也有局限性,因为父组件-子组件的连接必须全部在父组件的模板中进行。父组件本身的代码对子组件没有访问权。

如果父组件的类需要读取子组件的属性值或调用子组件的方法,就不能使用本地变量方法。

当父组件类需要这种访问时,可以把子组件作为 ViewChild,注入到父组件里面。

在上面定义好的子组件和父组件,我们可以看到:

父组件在组件类中通过@ViewChild()获取到子组件的实例,然后就可以在模板或者组件类中通过该实例获取子组件的属性:

<p>
 <!-- 通过组件类获取子组件示例,然后获取readyInfo属性,显示:子组件DemoChildComponent初始化完成! -->
 readyInfo: {{demoChildComponent.readyInfo}}
</p>
ngAfterViewInit() {
 console.log(this.demoChildComponent.readyInfo); // 打印结果:子组件DemoChildComponent初始化完成!
}

通过服务传递

Angular的服务可以在模块注入或者组件注入(均通过providers注入)。

在模块中注入的服务在整个Angular应用都可以访问(除惰性加载的模块)。

在组件中注入的服务就只能该组件和其子组件进行访问,这个组件子树之外的组件将无法访问该服务或者与它们通讯。

下面的示例就以在组件中注入的服务来进行父子组件之间的数据传递:

通讯的服务:

@Injectable()
export class CallService {
 info: string = '我是CallService的info';
}

父组件:

@Component({
 selector: 'demo-parent',
 template: `
 <demo-child></demo-child>
 <button (click)="changeInfo()">父组件改变info</button>
 <p>
  <!-- 显示:我是CallService的info -->
  {{callService.info}}
 </p>
 `,
 providers: [CallService]
})
export class DemoParentComponent {
 constructor(public callService: CallService) {
  console.log(callService.info); // 打印结果:我是CallService的info
 }
 
 changeInfo() {
  this.callService.info = '我是被父组件改变的CallService的info';
 }
}

子组件:

@Component({
 selector: 'demo-child',
 template: `
 <button (click)="changeInfo()">子组件改变info</button>
 `
})
export class DemoChildComponent {
 constructor(public callService: CallService) {
  console.log(callService.info); // 打印结果:我是CallService的info
 }
 
 changeInfo() {
  this.callService.info = '我是被子组件改变的CallService的info';
 }
}

相信看了本文案例你已经掌握了方法,更多精彩请关注php中文网其它相关文章!

推荐阅读:

css的新属性display:box使用方法

JS代码做出txt文件上传预览

위 내용은 Angular 구성요소와 상호작용하는 방법의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

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