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 ...
随机推荐
- 将传统应用带入浏览器的开源先锋「GitHub 热点速览」
现代浏览器已经不再是简单的浏览网页的工具,其潜能正在通过技术不断地被挖掘和扩展.得益于 WebAssembly 等技术的出现,让浏览器能够以接近原生的速度执行非 JavaScript 语言编写的程序, ...
- 基于CFX的小型风电机组流场计算流程
一.Workbench界面框架 二.Geometry模块操作 1.打开Geometry模块,导入txt格式模型 File >> Import External Geometry File ...
- vb.net 实现excel导入的时候滚动显示导入的数据
如果你想在 Excel 导入过程中滚动显示导入的数据,可以使用逐行读取 Excel 数据并在滚动窗口中显示. 在 VB.NET 中,你可以使用 Excel.Range 对象逐行读取 Excel 数据, ...
- Jax框架的static与Traced Operations —— Static vs Traced Operations
相关: Jax框架的jit编译是否可以使用循环结构,如果使用循环结构需要注意什么 Jax的static和Traced都是指jit编译的函数内的对象的属性的,jit装饰的函数其输入参数和输出参数都是Tr ...
- 什么样的AI计算框架才是受用户喜欢的?
说明,本文是个人的一些胡想. 背景: AI计算框架现在从国外的百家争鸣过度到了国内百家争鸣的局面了.在7.8年前的时候,国外的AI计算框架简直是数不胜数,从14.15年前Nvidia公司的显卡需要手动 ...
- ubuntu系统conda下运行pytorch报错:ImportError: libopenblas.so.0: cannot open shared object file
如题: ubuntu系统conda下运行pytorch报错:ImportError: libopenblas.so.0: cannot open shared object file 网上找了一些资料 ...
- 在Vue3中如何为路由Query参数标注类型
前言 最近发布了一款支持IOC容器的Vue3框架:Zova.与以往的OOP或者Class方案不同,Zova在界面交互层面仍然采用Setup语法,仅仅在业务层面引入IOC容器.IOC容器犹如一把钥匙,为 ...
- 新兴互联网银行搭档Apache SeaTunnel构建数据流通管道!
当新兴互联网银行乘着数字化改革的风潮搭档数据集成平台Apache SeaTunnel,成千万上亿的数据就有了快速流通的管道.6月26日14:00,Apache SeaTunnel社区将带上企业最佳实践 ...
- SeaTunnel JDBC DB2 Sink Connector支持的工作原理,快来学习吧!
DB2是IBM的一款关系型数据库管理系统,JDBC DB2 Source Connector是一个用于通过JDBC读取外部数据源数据的连接器.Apache SeaTunnel如何支持JDBC DB2 ...
- 基础数据结构->set&&map
set&&map BEGIN:惜墨如金 set用法 基本用法 #include<bits/stdc++.h> using namespace std; void the_s ...