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,理解组件元数据(selector、standalone、imports、template、styleUrls)的含义,并通过修改根组件app.ts把它接入应用布局,最后为Home添加带样式的搜索过滤框与按钮。读完本文,你可以独立完成"生成组件 → 注册到父模板 → 编写组件模板与样式"这一 Angular 开发最核心的循环,并理解仓库中 Component 装饰器 的底层默认值。
教程背景:first-app 的 14 课递进结构
first-app 教程位于 adev/src/content/tutorials/first-app 目录,由 intro 引导课和steps/下 14 个递进步骤组成(从01-hello-world到14-http),最终构建一个"房屋租赁列表 + 详情页"应用。每一课对应一个子目录,目录内既有一篇README.md讲解步骤,也有一份该步骤对应的完整可运行源码(src/目录)。
第 02 课 Create Home component 处于承上启下的位置:第 01 课你已把默认应用改造成显示 "Hello world";第 02 课要做的第一件事就是给应用添加第二个组件Home。
一个值得注意的细节是各步骤目录的"前后状态"约定:
- 02-Home/src 是执行本课之前的项目状态,此时
src/app/下只有app.ts和app.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-root、app-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), );两个实现细节值得注意:
Component是在Directive基础上通过makeDecorator派生的装饰器,即组件是"带模板的指令";- 归一化函数会把
changeDetection: ChangeDetectionStrategy.Eager作为默认值合并进配置——所以你不写changeDetection时,组件默认使用 Eager 变更检测策略。
步骤一:用 ng generate 创建 Home 组件
在 IDE 的Terminal面板中:
进入项目目录下的
first-app目录;运行命令创建新的
Home组件:ng generate component home运行命令构建并启动应用(此步仅限本地环境):
ng serve打开浏览器访问
http://localhost:4200;确认应用无错误构建完成。此时页面应与上一课完全一致——虽然你新增了组件,但还没有把它放进任何模板,所以界面上看不到任何变化。这正是 standalone 组件的工作方式:不注册、不引用,就不参与渲染;
保持
ng serve运行,继续后续步骤。
生成完成后,src/app/下会多出home/目录,包含home.ts和home.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 列;input与button的边框、背景色引用了 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.css | Home组件的作用域样式 |
| adev/src/content/tutorials/first-app/steps/03-HousingLocation/src/styles.css | 全局样式与主题色变量 |
| packages/core/src/metadata/directives.ts | Component装饰器与各元数据属性定义 |
适用前提:本仓库为 Angular 主线(main)分支,教程 starter 依赖 common/package.json 锁定的开发版本依赖(如@angular/core的22.x系列),因此本文描述的是 standalone 组件为默认形态的当前开发版行为;在你本地以稳定版 Angular CLI 复现时,命令与文件结构一致。下一课(03-HousingLocation)将在Home内部继续嵌套HousingLocation组件,进一步演示"组件中包含组件"的组合模式。
【免费下载链接】angularDeliver web apps with confidence 🚀项目地址: https://gitcode.com/GitHub_Trending/an/angular
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考