Angular 18+ 高级教程 – Component 组件 の Angular Component vs Web Component
前言
在 初识 Angular 中我有提到, Angular 团队是一群不爱创新、爱 follow 标准、爱小题大做的一群人。
所以,要理解 Angular Component,我们就非得要先搞懂远古的 Web Component 和 MVVM 的概念。
MVVM 和 Web Component
关于 MVVM 可以大约翻看这篇.
简单说一下,MVVM 就是让我们尽量不要像 jQuery 年代那样直接操作 DOM,而是通过框架提供的接口,间接的去操作 DOM。
为什么要这样?
第一是,操作 DOM 的代码很繁琐不好理解。你要可读性高,本来就需要封装成声明式,而现在框架就替你封装好了。
第二是,Angular 是框架,它控制了很多底层的东西,你如果绕过它,直接控制底层,一不小心就会和它撞上。所以 best practice 总是告诉你,尽量不要直接操作 DOM。
注:不要误会哦。它是说不要直接操作,但我们可以间接操作(使用 Angular 开放好的接口)。还有 "尽量" 不代表完全不要,只是要可控就可以了。
关于 Web Component,请务必先读完 DOM – Web Components 这篇,因为下面我会用到里面的例子,继续展开。
用 Angular Component 重写 Counter Component
在 DOM – Web Components 文章的结尾,我写了一个 Counter Component,我们现在用 Angular 重写一遍。
最终效果是这样

Step by Step
follow Angular 复习与进阶系列 – Get Started 搭建一个测试环境(这里我就不使用 inline style 和 inline template了,我不喜欢。)
ng new my-app --style=scss --routing=false --skip-tests --ssr=false
创建 Counter Component
cd src/app
ng g c counter
进入 counter.component.ts, 它目前长这样

CounterComponent 是一个类,我们要用它来描述下面这个 UI 组件。(Thinking in Angular Way)

以面向对象的方式来看,中间的号码可以用一个属性(property)来表示。
左右加减可以改变中间的号码,它们可以用方法(method)来表示。
所以,添加 number 属性和 add、minus 方法到 CounterComponent 里。


export class CounterComponent {
number = 0;
minus() {
this.number--;
}
plus() {
this.number++;
}
}
class 搞定,接下来我们进入 counter.component.html
先给它一个初始 HTML
<button>-</button>
<span>1</span>
<button>+</button>
我们要让它和刚才的 CounterComponent 对象,关联起来。
<span>{{ number }}</span>
这个是 Angular 其中一种关联语法。{{ number }} 就是对象里的 number 属性。
接着是左右按钮的点击事件,它们要关联到对象里的 add minus 方法。
<button (click)="minus()">-</button>
<span>{{ number }}</span>
<button (click)="plus()">+</button>
注:这个环节我们先不去探讨这些关联语法 binding syntax。我们继续往下。
接着就是加入 style
添加 class 到 HTML 作为 CSS selector
<button class="minus" (click)="minus()">-</button>
<span class="number">{{ number }}</span>
<button class="plus" (click)="plus()">+</button>
进入 counter.component.scss

:host {
display: flex;
gap: 16px;
:is(.minus, .plus) {
width: 64px;
height: 64px;
}
.number {
width: 128px;
height: 64px;
border: 1px solid gray;
font-size: 36px;
display: grid;
place-items: center;
}
}
没什么值得关注点,只是一些美观的 styles 而已。
至此,Counter Component 的部分就算完成了。
接着是如何使用它,我们进入到 app.component.ts。
import CounterComponent 到 AppComponent 中。

任何组件内想使用其它组件都必须先 import。
接着到 app.component.html
<app-counter></app-counter>
"app-" 是所有组件的 prefix,如果你不喜欢,可以通过 angular.json 做设置。
最后跑起来
ng serve --open
效果

对比 Angular Component 和 Web Component 实现的 Counter 组件
通过对比,我们可以看出 Angular 团队在设计 Angular Component 的思路,它们如何看待 Web Component 的缺陷,如何保留 Web Component 的设计理念,如何完善 Web Component。
最终保留了什么,丢弃了什么,增加了什么。搞清楚这些对学习和使用 Angular 非常重要,正所谓 Thinking in Angular Way 就是这样来的。
我们先理一下 Web Component 的整个流程
1. 定义 CounterComponent class

2. 做 Shadow DOM 隔离 CSS

3. 拦截初始化,通过 ajax 获取 template(如果你可以接受直接写 Raw HTML 在 TS 则可以省略掉这一步...)

4. 搞事件监听和渲染(DOM 操作)

5. define and use

上面 5 个 steps,Angular 都实现了。只是大部分实现代码都被隐藏了起来,我们主要写的是声明代码。

短短的几行代码,Angular 就 "声明" 了以下 4 个 steps
1. 定义 CounterComponent class
@Component 表示这个 class 是 Component
2. 做 Shadow DOM 隔离 CSS
Angular by default 所有 Component 都是隔离 CSS 的,不过它并不是通过 Shadow DOM 实现的。之后的教程会详细讲到。
3. 拦截初始化,通过 ajax 获取 template
Angular 是在 compile time 去链接 .html file 的,而 @Component.templateUrl 声明了 file 的位置。
5. define and use
@component.selector 声明了匹配的 selector
上面几个步骤, 我们都不需要写实现代码,只写声明代码就可以了。其它的交给 Angular。
还有一步是
4. 搞事件监听和渲染(DOM 操作)
这一步,Angular 用 MVVM 的方式来 "声明"。

同样的,我们不需要写任何操作 DOM 的代码。只要 "声明" 就可以了。.
从这些对比中,我们可以体会到,Angular 的设计理念就是尽可能把 "实现代码" 转换成 "声明代码"。
这个动机很好理解,一个长期维护的项目,代码分三种。
1. 实现代码
2. 可读性代码
3. 管理代码
实现代码就是让逻辑跑起来的代码。它们的特色就是繁琐、啰嗦、可读性差、难修改。
可读性代码就是我们声明的变量、方法名、类、接口等等。它们只是为了 "好读",你随便取名字并不影响程序的执行。
管理代码就是我们为了方便维护、修改、扩展、而做的各种封装代码。
项目越小,越不重视可读性代码和管理代码。而 Angular 的定位是长期维护的大项目,所以它的方向一定是让开发人员尽可能减少实现代码,提升可读性和管理代码。
Angular Component !== Web Component
Angular Component 虽然很大程度上借鉴了 Web Component,但是 Angular 并不是用 Shadow DOM + Custom Element 来实现 Web Component 的哦。
Angular 有一个扩展叫 Angular elements,它的方向是 convert Angular Component to 正真的 Web Component。也就是 Shadow Dom + Custom Element。
但目前这个项目有很多缺失的功能,而且没有得到足够的重视。希望未来不会被砍掉呗...
目录
上一篇 Angular 18+ 高级教程 – Dependency Injection 依赖注入
下一篇 Angular 18+ 高级教程 – Component 组件 の Angular Component vs Custom Elements
想查看目录,请移步 Angular 18+ 高级教程 – 目录
喜欢请点推荐,若发现教程内容以新版脱节请评论通知我。happy coding
Angular 18+ 高级教程 – Component 组件 の Angular Component vs Web Component的更多相关文章
- Angular CLI 使用教程指南参考
Angular CLI 使用教程指南参考 Angular CLI 现在虽然可以正常使用但仍然处于测试阶段. Angular CLI 依赖 Node 4 和 NPM 3 或更高版本. 安装 要安装Ang ...
- 示例可重用的web component方式组织angular应用模块
在online web应用中,经常有这样的需求,能够让用户通过浏览器来输入代码,同时能够根据不同的代码来做语法高亮.大家已知有很多相应的javascript库来实现语法高亮的功能,比如codemirr ...
- angular custom Element 自定义web component
angular 自定义web组件: 首先创建一个名为myCustom的组件. 引入app.module: ... import {customComponent} from ' ./myCustom. ...
- Vue教程:组件Component详解(六)
一.什么是组件? 组件 (Component) 是 Vue.js 最强大的功能之一.组件可以扩展 HTML 元素,封装可重用的代码.在较高层面上,组件是自定义元素,Vue.js 的编译器为它添加特殊功 ...
- angular2 学习笔记 ( Component 组件)
refer : https://angular.cn/docs/ts/latest/guide/template-syntax.html https://angular.cn/docs/ts/late ...
- 一篇文章看懂angularjs component组件
壹 ❀ 引 我在 angularjs 一篇文章看懂自定义指令directive 一文中详细介绍了directive基本用法与完整属性介绍.directive是个很神奇的存在,你可以不设置templa ...
- Angular 英雄示例教程
英雄指南教程(Tour of Heroes)涵盖了 Angular 的基本知识. 在本教程中,你将构建一个应用,来帮助人事代理机构来管理一群英雄. 这个入门级 app 包含很多数据驱动的应用所需的特性 ...
- [从 0 开始的 Angular 生活]No.38 实现一个 Angular Router 切换组件页面(一)
前言 今天是进入公司的第三天,为了能尽快投入项目与成为团队可用的战力,我正在努力啃官方文档学习 Angular 的知识,所以这一篇文章主要是记录我如何阅读官方文档后,实现这个非常基本的.带导航的网页应 ...
- NgRx/Store 4 + Angular 5使用教程
这篇文章将会示范如何使用NgRx/Store 4和Angular5.@ngrx/store是基于RxJS的状态管理库,其灵感来源于Redux.在NgRx中,状态是由一个包含action和reducer ...
- angular里使用vue/vue组件怎么在angular里用
欢迎加入前端交流群交流知识&&获取视频资料:749539640 如何在angularjs(1)中使用vue参考: https://medium.com/@graphicbeacon/h ...
随机推荐
- ps -ef | grep xxx 解释
上述内容为:命令拆解: ps:将某个进程显示出来-A 显示所有程序.-e 此参数的效果和指定"A"参数相同.-f 显示UID,PPIP,C与STIME栏位.grep命令是查找中间的 ...
- [oeasy]python0133_变量名_标识符_identifier_id_locals
变量名 回忆上次内容 上次讲了 什么是变量 变量变量 能变的量 就是变量 各种系统.游戏就是由变量所组成的 添加图片注释,不超过 140 字(可选) 声明了变量 并且 定义了变量 ...
- oeasy教您玩转vim - 82 - # 函数function
函数 function 回忆 关于宏,我们回忆一下 qa 开始录制宏 q 结束录制宏 @a 应用宏 qA 追加录制宏 控制寄存器内容其实就是控制宏 宏还有一些特性 可以多文件执行宏 可以并发运行宏 ...
- SQL Server 查询分析及优化方法
一.影响速度的因素 没有索引或者没有用到索引(这是查询慢最常见的问题,是程序设计的缺陷) I/O吞吐量小,形成了瓶颈效应 没有创建计算列导致查询不优化 内存不足 网络速度慢 查询出的数据量过大(可以采 ...
- ComfyUI进阶:Comfyroll插件 (六)
ComfyUI进阶:Comfyroll插件 (六) 前言: 学习ComfyUI是一场持久战,而Comfyroll 是一款功能强大的自定义节点集合,专为 ComfyUI 用户打造,旨在提供更加丰富和专业 ...
- MFC 完全自定义控件
头文件 #pragma once #include "pch.h" class CGridCtrl : public CWnd { public: void Create(CWnd ...
- .NET 高性能缓冲队列实现 BufferQueue
目录 前言 适用场景 功能说明 使用示例 BufferQueue 内部设计概述 Topic 的隔离 Partition 的设计 对并发的支持 Partition 的动态扩容 Segment 的回收机制 ...
- LVM综合实验
实验目标 创建并管理一个 LVM 卷组 (VG). 在卷组中创建.扩展和缩小逻辑卷 (LV). 创建和使用快照. 实验环境 Linux 服务器 三个可用的磁盘分区: /dev/sdb1, /dev/s ...
- python 抽卡
模拟抽奖 import random def main(): print('weilcome to box game') print(' 1.once\n','2.sixty times\n','3. ...
- HIC simple process
1,什么是Hic数据? Hi-C是研究染色质三维结构的一种方法.Hi-C技术源于染色体构象捕获(Chromosome Conformation Capture, 3C)技术,利用高通量测序技术,结合生 ...