面试题答案
一键面试性能优化
- Change Detection策略
- 默认策略调整:Angular默认采用的是
Default
变更检测策略,会在组件树的每个组件上运行变更检测。对于动态导航这种频繁更新的场景,可以将部分组件的变更检测策略设置为OnPush
。例如,导航菜单组件如果其输入属性(如菜单项数据)不经常变化,且不依赖于异步操作或DOM事件触发的变化,可以设置为OnPush
。这样只有当输入属性引用变化或者内部有事件触发时才会运行变更检测,减少不必要的检测开销。
@Component({ selector: 'app-navigation', templateUrl: './navigation.component.html', changeDetection: ChangeDetectionStrategy.OnPush }) export class NavigationComponent { // 组件逻辑 }
- 手动触发变更检测:对于
OnPush
策略下需要手动触发变更检测的情况,可以使用ChangeDetectorRef
。比如在动态加载子菜单后,如果需要更新视图,可以注入ChangeDetectorRef
并调用detectChanges
方法。
import { Component, ChangeDetectorRef } from '@angular/core'; @Component({ selector: 'app-sub - menu', templateUrl: './sub - menu.component.html', changeDetection: ChangeDetectionStrategy.OnPush }) export class SubMenuComponent { constructor(private cdr: ChangeDetectorRef) {} loadSubMenu() { // 加载子菜单逻辑 this.cdr.detectChanges(); } }
- 默认策略调整:Angular默认采用的是
- 优化指令的生命周期钩子函数
- ngOnInit:在
ngOnInit
钩子函数中尽量避免复杂的计算和大量的数据获取操作。对于导航菜单,菜单项的初始数据加载可以通过服务来完成,并在服务中进行缓存。这样在ngOnInit
中只需从服务获取缓存数据,而不是每次都重新获取。 - ngOnChanges:如果指令有输入属性,在
ngOnChanges
中只处理真正需要响应的属性变化。例如,导航菜单可能有一个表示当前选中菜单项的属性,只有当这个属性变化时才更新菜单的选中状态,而不是每次属性变化都进行全面的更新。 - ngDoCheck:谨慎使用
ngDoCheck
,因为它会在每个变更检测周期运行。如果必须使用,要确保其中的逻辑尽可能轻量。比如在导航菜单中,如果需要检查菜单项的某些自定义状态,可以在这里进行,但要避免复杂的DOM操作或数据计算。
- ngOnInit:在
SEO优化
- 服务器端渲染(SSR)
- 原理:服务器端渲染是指在服务器端生成完整的HTML页面,然后将其发送到客户端。这样搜索引擎爬虫访问页面时,能够直接获取到完整的导航结构和内容,而不需要等待客户端JavaScript执行来渲染页面。
- 实现:在Angular应用中,可以使用Angular Universal来实现服务器端渲染。首先安装
@angular - universal/express - engine
等相关依赖,然后配置服务器端渲染的入口文件和Express服务器。例如,在server.ts
文件中设置Express服务器来渲染Angular应用:
import { ngExpressEngine } from '@angular - universal/express - engine'; import { AppServerModule } from './src/main.server'; import { existsSync } from 'fs'; import express from 'express'; import { join } from 'path'; const app = express(); const distFolder = join(process.cwd(), 'dist/browser'); const indexHtml = existsSync(join(distFolder, 'index.original.html'))? 'index.original.html' : 'index'; app.engine('html', ngExpressEngine({ bootstrap: AppServerModule })); app.set('view engine', 'html'); app.set('views', distFolder); app.get('*.*', express.static(distFolder, { maxAge: '1y' })); app.get('*', (req, res) => { res.render(indexHtml, { req, providers: [] }); }); const port = process.env.PORT || 4000; app.listen(port, () => { console.log(`Node server listening on http://localhost:${port}`); });
- 使用Angular Meta服务
- 原理:Angular Meta服务可以帮助设置和管理HTML的元数据,如
title
、description
等。搜索引擎在抓取页面时会读取这些元数据来理解页面内容。对于动态导航,可以根据当前导航的状态(如选中的菜单项)来动态更新这些元数据。 - 实现:在组件中注入
Meta
服务,然后在需要的地方更新元数据。例如,在导航组件中根据当前选中菜单项更新页面标题:
import { Component } from '@angular/core'; import { Meta } from '@angular/platform - browser'; @Component({ selector: 'app - navigation', templateUrl: './navigation.component.html' }) export class NavigationComponent { constructor(private meta: Meta) {} onMenuItemSelect(menuItem) { this.meta.updateTag({ name: 'title', content: menuItem.title }); } }
- 原理:Angular Meta服务可以帮助设置和管理HTML的元数据,如
- 结构化数据标记(Schema.org)
- 原理:通过在HTML中添加结构化数据标记,搜索引擎能够更好地理解页面的内容结构。对于导航菜单,可以使用
JSON - LD
格式的结构化数据来描述菜单的层次结构、菜单项的链接、标题等信息。 - 实现:在页面的
head
部分添加script
标签,嵌入JSON - LD
格式的结构化数据。例如:
<script type="application/ld+json"> { "@context": "https://schema.org", "@type": "SiteNavigationElement", "name": "Main Navigation", "url": "/", "hasPart": [ { "@type": "SiteNavigationElement", "name": "Home", "url": "/" }, { "@type": "SiteNavigationElement", "name": "Products", "url": "/products", "hasPart": [ { "@type": "SiteNavigationElement", "name": "Product 1", "url": "/products/product1" }, { "@type": "SiteNavigationElement", "name": "Product 2", "url": "/products/product2" } ] } ] } </script>
- 原理:通过在HTML中添加结构化数据标记,搜索引擎能够更好地理解页面的内容结构。对于导航菜单,可以使用