Angular 组件实战:在 first-app 教程中创建并集成 Home 组件
2026/9/8 18:48:55 网站建设 项目流程

Angular 组件实战:在 first-app 教程中创建并集成 Home 组件

【免费下载链接】angularDeliver web apps with confidence 🚀项目地址: https://gitcode.com/GitHub_Trending/an/angular

本篇基于 Angular 仓库中的 first-app(构建你的第一个 Angular 应用)教程第 02 课 Create Home component 展开:你将完整掌握用ng generate component生成一个新组件Home,理解组件元数据(selectorstandaloneimportstemplatestyleUrls)的含义,并通过修改根组件app.ts把它接入应用布局,最后为Home添加带样式的搜索过滤框与按钮。读完本文,你可以独立完成"生成组件 → 注册到父模板 → 编写组件模板与样式"这一 Angular 开发最核心的循环,并理解仓库中 Component 装饰器 的底层默认值。

教程背景:first-app 的 14 课递进结构

first-app 教程位于 adev/src/content/tutorials/first-app 目录,由 intro 引导课和steps/下 14 个递进步骤组成(从01-hello-world14-http),最终构建一个"房屋租赁列表 + 详情页"应用。每一课对应一个子目录,目录内既有一篇README.md讲解步骤,也有一份该步骤对应的完整可运行源码src/目录)。

第 02 课 Create Home component 处于承上启下的位置:第 01 课你已把默认应用改造成显示 "Hello world";第 02 课要做的第一件事就是给应用添加第二个组件Home

一个值得注意的细节是各步骤目录的"前后状态"约定:

  • 02-Home/src 是执行本课之前的项目状态,此时src/app/下只有app.tsapp.css,还没有home目录——因为Home组件要靠本课的命令现场生成;
  • 02-Home/config.json 中"answerSrc": "../03-HousingLocation/src"声明了本课的"参考答案源码"位于下一课目录,即 03-HousingLocation/src 就是完成本课全部三步之后的最终代码。本文后续所有代码片段均取自该目录的真实文件。
{ "title": "Create home component", "type": "editor", "answerSrc": "../03-HousingLocation/src", "answerRootDir": "../03-HousingLocation", "openFiles": ["src/app/app.ts"] }

概念预备:Angular 组件是什么,元数据有哪些

Angular 应用以组件(component)为基本构建块。组件包含构成应用元素功能与外观的代码、HTML 布局和 CSS 样式信息;组件内部还可以包含其他组件,应用的功能和外观因此可以切分、组合到各个组件中。

创建Home组件时会用到以下五类元数据:

元数据作用本课示例
selector描述 Angular 在模板中如何引用该组件app-rootapp-home
standalone描述组件是否需要NgModule(当前默认即为 standalone,无需显式声明)省略,默认为独立组件
imports描述组件的模板依赖(其他组件、指令、管道)imports: [Home]
template描述组件的 HTML 标记与布局内联模板字符串
styleUrls以数组形式列出组件所用 CSS 文件的 URL['./home.css']

从源码结构看,这些属性在框架中的定义位置是 packages/core/src/metadata/directives.ts。其中imports属性的注释明确写道:它"only available for standalone components"——为声明在NgModule中的组件指定它会直接产生编译错误(见 directives.ts#L643)。这解释了为什么本课代码可以不做任何 NgModule 注册、直接在@Component里写imports: [Home]

Component装饰器本身的定义同样在该文件 directives.ts#L680-L686:

export const Component: ComponentDecorator = makeDecorator( 'Component', (c: Component = {}) => ({changeDetection: ChangeDetectionStrategy.Eager, ...c}), Directive, undefined, (type: Type<any>, meta: Component) => compileComponent(type, meta), );

两个实现细节值得注意:

  1. Component是在Directive基础上通过makeDecorator派生的装饰器,即组件是"带模板的指令";
  2. 归一化函数会把changeDetection: ChangeDetectionStrategy.Eager作为默认值合并进配置——所以你不写changeDetection时,组件默认使用 Eager 变更检测策略。

步骤一:用 ng generate 创建 Home 组件

在 IDE 的Terminal面板中:

  1. 进入项目目录下的first-app目录;

  2. 运行命令创建新的Home组件:

    ng generate component home
  3. 运行命令构建并启动应用(此步仅限本地环境):

    ng serve
  4. 打开浏览器访问http://localhost:4200

  5. 确认应用无错误构建完成。此时页面应与上一课完全一致——虽然你新增了组件,但还没有把它放进任何模板,所以界面上看不到任何变化。这正是 standalone 组件的工作方式:不注册、不引用,就不参与渲染;

  6. 保持ng serve运行,继续后续步骤。

生成完成后,src/app/下会多出home/目录,包含home.tshome.css(参照 03-HousingLocation/src/app/home 目录结构)。应用能正常启动的入口是 main.ts,它通过bootstrapApplication(App)引导根组件:

import {bootstrapApplication} from '@angular/platform-browser'; import {App} from './app/app'; bootstrapApplication(App).catch((err) => console.error(err));

步骤二:把 Home 加入应用布局

本步骤将Home添加到根组件App中,使其显示在应用布局里。修改 src/app/app.ts,共三处改动:

1. 在文件顶部导入Home(第 2 行):

import {Home} from './home/home';

2. 在@Component中把Home加入imports数组(第 6 行):

imports: [Home],

3. 用包含<app-home />的 HTML 替换template属性(第 7–16 行)。

完成后的app.ts完整内容如下(与仓库 03-HousingLocation/src/app/app.ts 一致):

import {Component} from '@angular/core'; import {Home} from './home/home'; @Component({ selector: 'app-root', imports: [Home], template: ` <main> <header class="brand-name"> <img class="brand-logo" src="/public/logo.svg" alt="logo" aria-hidden="true" /> </header> <section class="content"> <app-home /> </section> </main> `, styleUrls: ['./app.css'], }) export class App { title = 'homes'; }

这里体现了selector的实际用法:Home的 selector 是app-home,所以在父组件模板中以<app-home />标签形式出现;而App的 selector 是app-root,对应index.html中的挂载点。

保存后,若ng serve正在运行则应用自动热更新;原本显示 "Hello world" 的位置将被Home组件的默认模板替换。组件的:host级样式(如 app.css 中的头部阴影)依旧作用在根组件上。

步骤三:为 Home 添加搜索过滤框与按钮

上一课只是把Home的默认模板渲染了出来。这一步给它加上一个搜索过滤器(filter)文本输入框和 Search 按钮——供后续课程实现"按城市过滤房源"功能使用。注意:本步骤只往布局中加入这些元素,尚不绑定任何功能逻辑

1. 修改 src/app/home/home.ts 的template属性(完整文件如下):

import {Component} from '@angular/core'; @Component({ selector: 'app-home', template: ` <section> <form> <input type="text" placeholder="Filter by city" /> <button class="primary" type="button">Search</button> </form> </section> `, styleUrls: ['./home.css'], }) export class Home {}

styleUrls: ['./home.css']指向与组件同目录的样式文件。组件样式是作用域样式(scoped styles):home.css中的规则只作用于Home组件模板内的元素,这也是把样式写在组件文件而非全局文件的原因。

2. 用以下规则替换 src/app/home/home.css 的内容(完整文件):

.results { display: grid; column-gap: 14px; row-gap: 14px; grid-template-columns: repeat(auto-fill, minmax(400px, 400px)); margin-top: 50px; justify-content: space-around; } input[type="text"] { border: solid 1px var(--primary-color); padding: 10px; border-radius: 8px; margin-right: 4px; display: inline-block; width: 30%; } button { padding: 10px; border: solid 1px var(--primary-color); background: var(--primary-color); color: white; border-radius: 8px; } @media (min-width: 500px) and (max-width: 768px) { .results { grid-template-columns: repeat(2, 1fr); } input[type="text"] { width: 70%; } } @media (max-width: 499px) { .results { grid-template-columns: 1fr; } }

说明几个取值细节:

  • .results网格虽然本课尚未渲染列表,但已为第 04 课之后的房源卡片(HousingLocation组件)预留了repeat(auto-fill, minmax(400px, 400px))的响应式布局,并在 500–768px、499px 以下两档断点降级为 2 列和 1 列;
  • inputbutton的边框、背景色引用了 CSS 变量var(--primary-color)

3. 如果你是从全新的ng new项目(而非教程提供的 starter 包)开始,需要把以下全局样式加入src/styles.css,否则搜索按钮和输入框的边框不可见(变量定义在全局,按钮类样式供button.primary使用):

:root { --primary-color: #605DC8; --secondary-color: #8B89E6; --accent-color: #e8e7fa; --shadow-color: #E8E8E8; } button.primary { padding: 10px; border: solid 1px var(--primary-color); background: var(--primary-color); color: white; border-radius: 8px; }

这正是 starter 源码 03-HousingLocation/src/styles.css 的内容:它在全局:root上定义了四个主题色变量(primary/secondary/accent/shadow),并全局定义了button.primary外观;组件级home.css则引用这些变量完成局部样式。

4. 确认应用无错误构建,页面中应能看到带样式的过滤输入框和 Search 按钮。若样式没生效,优先检查var(--primary-color)这类全局变量是否已写入styles.css

本课小结与关键文件索引

本课完成后的能力:你创建了应用中的第一个非根组件Home,把它注册进根组件的imports并以<app-home />挂入模板,同时为它编写了内联模板与作用域样式,为后续"按城市过滤房源"的功能打好了 UI 基础。

关键文件速查:

文件说明
adev/src/content/tutorials/first-app/steps/02-Home/README.md本课原文档(三步流程)
adev/src/content/tutorials/first-app/steps/02-Home/src/app/app.ts执行本课前的根组件(仅显示 Hello world)
adev/src/content/tutorials/first-app/steps/03-HousingLocation/src/app/app.ts本课完成后的根组件(导入并挂载Home
adev/src/content/tutorials/first-app/steps/03-HousingLocation/src/app/home/home.ts含过滤框与按钮的Home组件
adev/src/content/tutorials/first-app/steps/03-HousingLocation/src/app/home/home.cssHome组件的作用域样式
adev/src/content/tutorials/first-app/steps/03-HousingLocation/src/styles.css全局样式与主题色变量
packages/core/src/metadata/directives.tsComponent装饰器与各元数据属性定义

适用前提:本仓库为 Angular 主线(main)分支,教程 starter 依赖 common/package.json 锁定的开发版本依赖(如@angular/core22.x系列),因此本文描述的是 standalone 组件为默认形态的当前开发版行为;在你本地以稳定版 Angular CLI 复现时,命令与文件结构一致。下一课(03-HousingLocation)将在Home内部继续嵌套HousingLocation组件,进一步演示"组件中包含组件"的组合模式。

【免费下载链接】angularDeliver web apps with confidence 🚀项目地址: https://gitcode.com/GitHub_Trending/an/angular

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询