前言

在 初识 Angular 中我有提到, Angular 团队是一群不爱创新、爱 follow 标准、爱小题大做的一群人。

所以,要理解 Angular Component,我们就非得要先搞懂远古的 Web ComponentMVVM 的概念。

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的更多相关文章

  1. Angular CLI 使用教程指南参考

    Angular CLI 使用教程指南参考 Angular CLI 现在虽然可以正常使用但仍然处于测试阶段. Angular CLI 依赖 Node 4 和 NPM 3 或更高版本. 安装 要安装Ang ...

  2. 示例可重用的web component方式组织angular应用模块

    在online web应用中,经常有这样的需求,能够让用户通过浏览器来输入代码,同时能够根据不同的代码来做语法高亮.大家已知有很多相应的javascript库来实现语法高亮的功能,比如codemirr ...

  3. angular custom Element 自定义web component

    angular 自定义web组件: 首先创建一个名为myCustom的组件. 引入app.module: ... import {customComponent} from ' ./myCustom. ...

  4. Vue教程:组件Component详解(六)

    一.什么是组件? 组件 (Component) 是 Vue.js 最强大的功能之一.组件可以扩展 HTML 元素,封装可重用的代码.在较高层面上,组件是自定义元素,Vue.js 的编译器为它添加特殊功 ...

  5. angular2 学习笔记 ( Component 组件)

    refer : https://angular.cn/docs/ts/latest/guide/template-syntax.html https://angular.cn/docs/ts/late ...

  6. 一篇文章看懂angularjs component组件

     壹 ❀ 引 我在 angularjs 一篇文章看懂自定义指令directive 一文中详细介绍了directive基本用法与完整属性介绍.directive是个很神奇的存在,你可以不设置templa ...

  7. Angular 英雄示例教程

    英雄指南教程(Tour of Heroes)涵盖了 Angular 的基本知识. 在本教程中,你将构建一个应用,来帮助人事代理机构来管理一群英雄. 这个入门级 app 包含很多数据驱动的应用所需的特性 ...

  8. [从 0 开始的 Angular 生活]No.38 实现一个 Angular Router 切换组件页面(一)

    前言 今天是进入公司的第三天,为了能尽快投入项目与成为团队可用的战力,我正在努力啃官方文档学习 Angular 的知识,所以这一篇文章主要是记录我如何阅读官方文档后,实现这个非常基本的.带导航的网页应 ...

  9. NgRx/Store 4 + Angular 5使用教程

    这篇文章将会示范如何使用NgRx/Store 4和Angular5.@ngrx/store是基于RxJS的状态管理库,其灵感来源于Redux.在NgRx中,状态是由一个包含action和reducer ...

  10. angular里使用vue/vue组件怎么在angular里用

    欢迎加入前端交流群交流知识&&获取视频资料:749539640 如何在angularjs(1)中使用vue参考: https://medium.com/@graphicbeacon/h ...

随机推荐

  1. adorner 使用示例

    模块介绍 adorner 是一个现代轻量级的 Python 装饰器辅助模块. 目前该模块仅实现了 4 个类,对应着 4 个功能:制造装饰器.执行计时.函数缓存.捕获重试. 仓库地址:https://g ...

  2. 从基础到高级应用,详解用Python实现容器化和微服务架构

    本文分享自华为云社区<Python微服务与容器化实践详解[从基础到高级应用]>,作者: 柠檬味拥抱. Python中的容器化和微服务架构实践 在现代软件开发中,容器化和微服务架构已经成为主 ...

  3. 为什么学编程都从helloworld开始?

    你好世界 回忆上次内容 上次 了解了 游乐场规则 REPL       添加图片注释,不超过 140 字(可选)   print函数 可以输出 字符串"h"     添加图片注释, ...

  4. ArchLinux Vmware安装指北

    ArchLinux Vmware安装指北 在本文开始之前,首先允许我提前声明一点,Arch Linux的安装并不算难,但是绝对也算不上简单,中间的安装可能会遇到很多问题,本篇文章不能保证完全贴合你的真 ...

  5. rtmp流程解析

    如果rtmp推流地址:rtmp://服务器地址:rtmp端口/路径/名称对应的websocket地址:ws://服务器地址:websocket端口/路径/名称.flv举例:live作为路径,s作为流名 ...

  6. stream流的概述以及idea与stream

    前面自己学过一些流的概念,比如IO流,用于读写本地的数据. stream流主要是用于对集合/数组进行操作 idea现在已经很好的支持Stream流操作,在debug的时候可以很好的看到详细内容 下面以 ...

  7. JAVA并发编程理论基础

    注:本文章是对极客时间<java并发编程实战>学习归纳总结,更多知识点可到原文 java并发编程实战 进行学习.如果侵权,联系删除: 一.并发编程的BUG的源头 1.1 缓存导致的可见性问 ...

  8. .NET 结果与错误处理利器 FluentResults

    前言 在项目开发中,方法返回的结果(成功或失败)对我们开发来说很重要.传统方法,如通过异常来指示错误或使用特定的返回类型(如布尔值加输出参数),虽然有效,但可能缺乏直观性和灵活性. FluentRes ...

  9. 【MySQL】拆分经纬度字段

    数据结构: 表中一字段存储经度和纬度: +---------------------------+ | INSTALL_LOLA_NUM | +---------------------------+ ...

  10. win10开启窗口左右分屏方法

    首先进入导航栏(等同于按下win徽标): 之后点击电源键上的"设置": 进入"系统" 左边一栏里点击"多任务处理" 打开"贴靠窗囗 ...