MST

星途 面试题库

面试题:Angular与Vue在组件化方面的主要区别

请详细阐述Angular和Vue在组件化设计上的主要差异,包括组件的定义方式、数据传递机制以及生命周期钩子函数的使用特点等方面。
24.6万 热度难度
前端开发Angular

知识考点

AI 面试

面试题答案

一键面试

组件定义方式

  • Angular
    • 使用TypeScript类来定义组件。通过装饰器@Component来标识一个类为组件,并在装饰器中配置组件的元数据,如selector(用于在HTML中选择该组件)、templateUrl(组件模板文件路径)、styleUrls(组件样式文件路径)等。例如:
import { Component } from '@angular/core';

@Component({
  selector: 'app - my - component',
  templateUrl: './my - component.html',
  styleUrls: ['./my - component.css']
})
export class MyComponent {
  // 组件逻辑代码
}
  • 模板使用Angular的模板语法,支持插值、指令等,与组件类紧密结合。
  • Vue
    • 有多种方式定义组件。可以使用对象字面量形式,也可以使用单文件组件(.vue文件)。在单文件组件中,<template>标签定义组件的模板结构,<script>标签定义组件的逻辑(通常是JavaScript或TypeScript),<style>标签定义组件的样式。例如:
<template>
  <div>
    <p>{{ message }}</p>
  </div>
</template>

<script>
export default {
  data() {
    return {
      message: 'Hello, Vue!'
    };
  }
};
</script>

<style scoped>
div {
  color: blue;
}
</style>
  • 语法相对更简洁,模板和逻辑代码的分离更直观。

数据传递机制

  • Angular
    • 父子组件:父组件通过绑定属性向子组件传递数据。在子组件类中使用@Input()装饰器来接收父组件传递的数据。例如,父组件模板中:<app - child - component [inputValue]="parentData"></app - child - component>,子组件类中:
import { Component, Input } from '@angular/core';

@Component({
  selector: 'app - child - component',
  templateUrl: './child - component.html'
})
export class ChildComponent {
  @Input() inputValue;
}
  • 子父组件:子组件通过@Output()装饰器和EventEmitter来向父组件发送事件和数据。子组件触发事件,父组件在模板中监听该事件并处理数据。例如,子组件类中:
import { Component, Output, EventEmitter } from '@angular/core';

@Component({
  selector: 'app - child - component',
  templateUrl: './child - component.html'
})
export class ChildComponent {
  @Output() dataToParent = new EventEmitter();

  sendData() {
    this.dataToParent.emit('Some data from child');
  }
}
  • 父组件模板中:<app - child - component (dataToParent)="handleChildData($event)"></app - child - component>
  • 非父子组件:通常使用服务(Service)来共享数据。服务是一个单例对象,不同组件可以注入同一个服务实例,通过服务来传递和共享数据。
  • Vue
    • 父子组件:父组件通过属性绑定向子组件传递数据。子组件在props选项中声明要接收的属性。例如,父组件模板中:<child - component :input - value="parentData"></child - component>,子组件中:
export default {
  props: ['inputValue'],
  // 组件逻辑
}
  • 子父组件:子组件通过$emit方法触发自定义事件并传递数据给父组件。父组件在模板中监听该自定义事件。例如,子组件中:this.$emit('send - data', 'Some data from child');,父组件模板中:<child - component @send - data="handleChildData"></child - component>
  • 非父子组件:对于简单场景可以使用Vue.prototype挂载一个全局事件总线来实现数据传递;对于复杂状态管理,Vuex是常用的解决方案,它通过集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。

生命周期钩子函数使用特点

  • Angular
    • 创建阶段
      • ngOnInit:在组件初始化完成后调用,此时组件的输入属性已绑定,可以在此进行数据初始化、订阅Observable等操作。
      • ngOnChanges:当组件的输入属性发生变化时调用,首次绑定也会调用。可以在此处理输入属性变化带来的逻辑。
    • 更新阶段
      • ngDoCheck:每次变更检测运行时调用,可在此实现自定义的变更检测逻辑,但频繁调用可能影响性能,使用需谨慎。
      • ngAfterContentInit:当组件内容(<ng - content>投影的内容)初始化完成后调用。
      • ngAfterContentChecked:每次组件内容检查完成后调用。
      • ngAfterViewInit:当组件视图(包括子视图)初始化完成后调用,可在此操作DOM。
      • ngAfterViewChecked:每次组件视图检查完成后调用。
    • 销毁阶段ngOnDestroy:在组件销毁前调用,可在此取消订阅、清理定时器等操作,防止内存泄漏。
  • Vue
    • 创建阶段
      • beforeCreate:实例刚被创建,数据观测和事件机制未初始化,此时无法访问数据和方法。
      • created:实例创建完成,数据观测和事件机制已就绪,可以访问数据和方法,可在此进行数据获取等操作。
    • 挂载阶段
      • beforeMount:在挂载开始之前被调用,此时模板已编译,但尚未挂载到DOM,$el属性还不存在。
      • mounted:实例被挂载后调用,此时可以访问挂载的DOM元素,可进行DOM操作等。
    • 更新阶段
      • beforeUpdate:数据更新时调用,此时DOM还未更新,可在更新前访问现有DOM状态。
      • updated:数据更新且DOM更新完成后调用,可在此操作更新后的DOM。
    • 销毁阶段
      • beforeDestroy:实例销毁前调用,实例仍然可用,可在此清理定时器、解绑事件等。
      • destroyed:实例销毁后调用,所有指令已解绑,事件监听器已移除,子实例也已销毁。