六个月前,我们将独立 API从开发人员预览中升级,从而在 Angular 的简单性和开发人员体验方面达到了一个重要的里程碑。今天,我们很高兴地宣布,我们将继续 Angular Momentum,推出自 Angular 首次推出以来最大的版本;在反应性、服务器端渲染和工具方面取得巨大飞跃。所有这一切都伴随着跨功能请求的数十项生活质量改进,在 GitHub 上获得了 2,500 多个赞!
Angular v16 版本
作为 v16 版本的一部分,我们很高兴与大家分享一个全新的 Angular 反应模型的开发者预览,它显着改善了性能和开发者体验。
它完全向后兼容并可与当前系统互操作,并支持:
最初的GitHub 讨论获得了 682 条评论,从那时起我们分享了一系列 RFC,收到了超过 1,000 条评论!
在 v16 中,您可以找到一个新的信号库,它是@angular/coreRxJS 互操作包的一部分@angular/core/rxjs-interop,框架中的完整信号集成将于今年晚些时候推出。
@angular/core
@angular/core/rxjs-interop
Angular 信号库允许你定义响应值并表达它们之间的依赖关系。您可以在相应的 RFC中了解有关库属性的更多信息。这是一个如何将它与 Angular 一起使用的简单示例:
@Component({ selector: 'my-app', standalone: true, template: ` {{ fullName() }} <button (click)="setName('John')">Click</button> `, }) export class App { firstName = signal('Jane'); lastName = signal('Doe'); fullName = computed(() => `${this.firstName()} ${this.lastName()}`); constructor() { effect(() => console.log('Name changed:', this.fullName())); } setName(newName: string) { this.firstName.set(newName); } }
上面的代码片段创建了一个计算值fullName,它取决于信号firstName和lastName。我们还声明了一个效果,每当我们更改它读取的任何信号的值时,回调都会执行——在本例中,fullName这意味着它也传递地依赖于firstName和lastName。
fullName
firstName
lastName
当我们将 的值设置firstName为“John”时,浏览器将登录到控制台:
"Name changed: John Doe"
@angular/core/rxjs-interop作为 v16 版本的一部分,您将能够通过开发人员预览中的函数轻松地将信号“提升”到可观察对象!
以下是将信号转换为可观察信号的方法:
import { toObservable, signal } from '@angular/core/rxjs-interop'; @Component({...}) export class App { count = signal(0); count$ = toObservable(this.count); ngOnInit() { this.count$.subscribe(() => ...); } }
…这是一个示例,说明如何将可观察对象转换为信号以避免使用异步管道:
import {toSignal} from '@angular/core/rxjs-interop'; @Component({ template: ` <li *ngFor="let row of data()"> {{ row }} </li> ` }) export class App { dataService = inject(DataService); data = toSignal(this.dataService.data$, []); }
Angular 用户通常希望在相关主题完成时完成流。以下说明性模式非常常见:
destroyed$ = new ReplaySubject<void>(1); data$ = http.get('...').pipe(takeUntil(this.destroyed$)); ngOnDestroy() { this.destroyed$.next(); }
我们正在引入一个名为 的新 RxJS 运算符takeUntilDestroy,它将此示例简化为以下内容:
takeUntilDestroy
data$ = http.get('…').pipe(takeUntilDestroyed());
默认情况下,此运算符将注入当前清理上下文。比如在组件中使用,会使用组件的生命周期。
takeUntilDestroy当您想将 Observable 的生命周期与特定组件的生命周期联系起来时,它特别有用。
接下来,我们将研究基于信号的组件,这些组件具有一组简化的生命周期挂钩,以及另一种更简单的声明输入和输出的方法。我们还将致力于更完整的示例和文档集。
Angular 存储库中最受欢迎的问题之一是“建议:作为可观察输入”。几个月前,我们回应说我们希望支持这个用例,作为框架中更大努力的一部分。我们很高兴与大家分享,今年晚些时候我们将推出一项功能,支持基于信号的输入——您将能够通过互操作包将输入转换为可观察对象!
根据我们的年度开发人员调查,服务器端渲染是 Angular 改进的首要机会。在过去的几个月里,我们与Chrome Aurora 团队合作改进了水化和服务器端渲染的性能和 DX。今天我们很高兴分享完整应用程序无损水化的开发者预览!
在新的完整应用程序非破坏性水合作用中,Angular 不再从头开始重新渲染应用程序。相反,该框架在构建内部数据结构时查找现有的 DOM 节点,并将事件侦听器附加到这些节点。
好处是:
ngSkipHydration
在早期测试中,我们看到Largest Contentful Paint的改进高达 45%,并具有完整的应用程序水合作用!
要开始使用它就像在您的中添加几行一样简单main.ts:
main.ts
import { bootstrapApplication, provideClientHydration, } from '@angular/platform-browser'; ... bootstrapApplication(RootCmp, { providers: [provideClientHydration()] });
您可以在文档中找到有关其工作原理的更多详细信息。
作为 v16 版本的一部分,我们还更新了 Angular Universal 的 ng add schematics,使您能够使用独立 API 将服务器端渲染添加到项目中。我们还为内联样式引入了对更严格的内容安全策略的支持。
我们计划在这里做更多的事情,v16 中的工作只是垫脚石。在某些情况下,有机会延迟加载对页面不重要的 JavaScript,并在以后混合相关组件。这种技术被称为部分水化,我们接下来将对其进行探索。
自从 Qwik 从 Google 的封闭源代码框架 Wiz 中普及了可恢复性的想法后,我们收到了很多对 Angular 中此功能的请求。可恢复性肯定在我们的关注范围内,我们正在与 Wiz 团队密切合作探索这个领域。我们对其带来的对开发人员体验的限制持谨慎态度,评估不同的权衡,并会在我们取得进展时及时通知您。
您可以在“ Angular 中服务器端渲染的下一步是什么”中阅读更多关于我们未来计划的信息。
Angular 是数百万开发人员用于许多关键任务应用程序的框架,我们认真对待重大变化。几年前我们开始探索独立的 API ,在 2022 年我们在开发者预览版下发布了它们。现在,经过一年多的收集反馈和迭代 API,我们希望鼓励更广泛的采用!
为了支持开发人员将他们的应用程序转换为独立 API,我们开发了迁移示意图和独立迁移指南。进入项目目录后运行:
ng generate @angular/core:standalone
原理图将转换您的代码,删除不必要的NgModules类,并最终更改项目的引导程序以使用独立的 API。
NgModules
作为 Angular v16 的一部分,您可以从一开始就独立创建新项目!要尝试独立原理图的开发人员预览,请确保您使用的是 Angular CLI v16 并运行:
ng new --standalone
您将获得一个更简单的项目输出,没有任何NgModules. 此外,项目中的所有生成器都将生成独立的指令、组件和管道!
在独立 API 首次发布后,我们从开发人员那里得知您希望能够使用新bootstrapApplicationAPI配置 Zone.js。
bootstrapApplication
我们为此添加了一个选项provideZoneChangeDetection:
provideZoneChangeDetection
bootstrapApplication ( App , { providers : [ provideZoneChangeDetection ({ eventCoalescing : true })] });
现在,让我们分享 Angular CLI 和语言服务的一些功能亮点。
一年多以前,我们宣布我们正在努力为 Angular CLI 中的 esbuild 提供实验性支持,以使您的构建速度更快。今天,我们很高兴地与大家分享,在 v16 中,我们基于 esbuild 的构建系统进入了开发者预览版!早期测试表明,冷生产构建的改进超过 72%。
基于 esbuild 的构建器的开发者预览版
我们ng serve现在使用 Vite 作为开发服务器,而 esbuild 为您的开发和生产构建提供支持!
ng serve
我们要强调的是 Angular CLI 完全依赖 Vite 作为开发服务器。为了支持选择器匹配,Angular 编译器需要维护组件之间的依赖图,这需要与 Vite 不同的编译模型。
你可以通过更新你的:来尝试 Vite + esbuild angular.json:
angular.json
... "architect" : { "build" : { /* 添加 esbuild 后缀 */ "builder" : "@angular-devkit/build-angular:browser-esbuild" , ...
接下来我们将解决对 i18n 的支持,然后再从开发人员预览中毕业这个项目。
根据 Angular 和更广泛的 JavaScript 社区中的开发人员调查,Jest是最受欢迎的测试框架和测试运行器之一。我们收到了大量支持 Jest 的请求,由于不需要真正的浏览器,因此复杂性降低了。
今天,我们很高兴地宣布我们将引入实验性的 Jest 支持。在未来的版本中,我们还将现有的Karma项目移至Web Test Runner,以继续支持基于浏览器的单元测试。对于大多数开发人员来说,这将是一个空操作。
npm install jest --save-dev您可以通过安装 Jest并更新文件来在新项目中试验 Jest angular.json:
npm install jest --save-dev
{ "projects": { "my-app": { "architect": { "test": { "builder": "@angular-devkit/build-angular:jest", "options": { "tsConfig": "tsconfig.spec.json", "polyfills": ["zone.js", "zone.js/testing"] } } } } } }
您可以在我们最近的博客文章中了解有关我们未来单元测试策略的更多信息。
您有多少次在模板中使用组件或管道从 CLI 或语言服务中获取您实际上没有导入相应实现的错误?我打赌很多次!
语言服务现在允许自动导入组件和管道。
Angular 语言服务自动导入
Gif 显示了 VSCode 中 Angular 语言服务的自动导入功能
在 v16 中,我们还启用了对 TypeScript 5.0 的支持,支持ECMAScript装饰器,消除了 ngcc 的开销,在独立应用程序中添加了对service workers和app shell的支持,扩展了CLI 中的 CSP 支持,等等!
除了我们关注的大型计划外,我们还致力于带来高度要求的功能。
自从我们在 2016 年引入 Angular 以来,如果您不为特定输入指定值,就不可能出现编译时错误。由于 Angular 编译器在构建时执行检查,因此更改在运行时增加了零开销。多年来,开发人员一直 要求 此功能 ,我们得到了一个强烈的迹象,表明这将非常方便!
在 v16 中,您现在可以根据需要标记输入:
@Component (...) export class App { @Input ({ required : true }) title : string = '' ; }
路由器的开发人员体验一直在快速发展。GitHub 上一个流行的功能请求是要求能够将路由参数绑定到相应组件的输入。我们很高兴地告诉大家,此功能现已作为 v16 版本的一部分提供!
现在您可以将以下数据传递给路由组件的输入:
以下是如何从路由解析器访问数据的示例:
const routes = [ { path : 'about' , loadComponent : import ( './about' ), resolve : { contact : () => getContact () } } ]; @Component (...) export class About { // 将“contact”的值传递给contact input @Input () contact?: string ; }
Angular 在组件样式的 DOM 中包含的内联样式元素违反了默认的style-src 内容安全策略 (CSP)。要解决这个问题,它们应该包含一个nonce属性,或者服务器应该在 CSP 标头中包含样式内容的散列。尽管在谷歌我们没有找到针对此漏洞的有意义的攻击向量,但许多公司执行严格的 CSP,导致对 Angular 存储库的功能请求的流行。
style-src
nonce
nonce在 Angular v16 中,我们实现了一个跨越框架、Universal、CDK、Material 和 CLI 的新功能,它允许您为 Angular 内联的组件的样式指定一个属性。有两种方法可以指定随机数:使用属性ngCspNonce或通过CSP_NONCE注入令牌。
ngCspNonce
CSP_NONCE
如果您有权访问可以将两者添加到标头和构建响应时的ngCspNonce服务器端模板,则该属性很有用。nonceindex.html
index.html
<html> <body> <app ngCspNonce="{% nonce %}"></app> </body> </html>
另一种指定随机数的方法是通过CSP_NONCE注入令牌。如果您有权在运行时访问nonce并且希望能够缓存,请使用此方法index.html:
import {bootstrapApplication, CSP_NONCE} from '@angular/core'; import {AppComponent} from './app/app.component'; bootstrapApplication(AppComponent, { providers: [{ provide: CSP_NONCE, useValue: globalThis.myRandomNonceValue }] });
Angular 的生命周期钩子提供了强大的功能来插入应用程序执行的不同时刻。多年来的一个机会是实现更高的灵活性,例如,提供对OnDestroy 作为 observable 的访问。
在 v16 中,我们使 OnDestroy 可注入,从而实现开发人员一直要求的灵活性。这个新功能允许您注入DestroyRef对应的组件、指令、服务或管道——并注册onDestroy生命周期挂钩。可以DestroyRef在注入上下文中的任何地方注入,包括组件外部——在这种情况下,onDestroy当相应的注入器被销毁时,钩子就会被执行:
DestroyRef
onDestroy
import { Injectable, DestroyRef } from '@angular/core'; @Injectable(...) export class AppService { destroyRef = inject(DestroyRef); destroy() { this.destroyRef.onDestroy(() => /* cleanup */ ); } }
我们最近实现的一项非常受欢迎的功能允许您为 Angular 模板中的组件使用自闭合标签。这是一个小的开发人员体验改进,可以节省您的输入时间!
现在你可以替换:
< super-duper-long-component-name [ prop ]= "someVar" > </ super-duper-long-component-name >
有了这个:
< super-duper-long-component-name [ prop ]= "someVar" />
在过去的几个季度中,我们与 Google 的 Material Design 团队密切合作,为 Web 和 Angular Material 提供参考 Material 3 实现。我们在 2022 年发布的基于 Web 的 MDC 组件为这项工作奠定了基础。
作为下一步,我们正努力在今年晚些时候推出一个基于令牌的富有表现力的主题 API,以实现 Angular 材质组件的更高定制化。
提醒一下,我们将在 v17 中删除遗留的、非基于 MDC 的组件。请确保您按照我们的迁移指南迁移到最新版本。
遵循 Google 的使命,Angular 可让您为所有人构建 Web 应用程序!这就是为什么我们不断投资以提高Angular CDK 和 Material 组件的可访问性。
我们要强调的社区引入的两个功能是:
provideServiceWorker
超过 175 人在 GitHub 上为 v16 做出了贡献,还有数千人通过博客文章、演讲、播客、视频、对反应性 RFC 的评论等做出了贡献。
我们非常感谢所有帮助我们使这个版本变得特别的人。
版本 16 是明年 Angular 的反应性和服务器端渲染未来改进的垫脚石。我们将通过在开发人员体验和性能方面进行创新来推动 Web 向前发展,同时让您能够为每个人构建!
你可以成为 Angular Momentum 的一员,通过在即将到来的 RFC、调查或社交媒体中分享你的想法来帮助我们塑造框架的未来。
感谢您成为 Angular 社区的一员。我们迫不及待地想让您尝试这些功能!
本文分享自華爲雲社區《JDBC連接openGauss6.0和PostgreSQL16.2性能對比》,作者: Gauss松鼠會小助手。 PostgreSQL vs openGauss 01 前置準備 安裝JDK: 詳細安裝步驟請問度娘,輸
本文分享自華爲雲社區《Python函數與模塊的精髓與高級特性》,作者:檸檬味擁抱。 Python 是一種功能強大的編程語言,擁有豐富的函數和模塊,使得開發者能夠輕鬆地構建複雜的應用程序。本文將介紹 Python 中函數和模塊的基本使用方法,
'./common/vendor.js' 微信開發工具打開詳情》本地設置》將JS編譯ES5 將選擇去掉 就不會了
<?php /** * *************************************** * 單進程保護 * * **************************
01 背 景 播放鏈路是愛奇藝最重要的業務,鏈路穩定性極其重要,隨着愛奇藝用戶的不斷增長和熱播劇集的推廣,播放鏈路往往面臨着難以預估的用戶流量的突增,考
給大家30秒的時間,一起來思考這是什麼? 這是某系統登陸模塊功能的初始類圖。 隨着現代軟件的不斷複雜化,代碼圖(Code Graphs)爲測試人員提供了一種直觀的方法,讓複雜的代碼邏輯易於理解。本文將深入探討代碼圖,通過挖掘到的真實場景
1 前言: 大家都知道,阿里規範中有一條是不允許用excutors去創建線程池,而是採用ThreadPoolExecutor的原生方式去創建。很早就聽過所過這種說法,但是一直都沒去搞清楚是爲什麼,今天就查閱資料去了解了這
使用jasypt工具加密 在maven中引入jasypt依賴包: <dependency> <groupId>com.test.caep</groupId> <artifactId>jasypt-spring-boot-st
1.redis未授權訪問漏洞 通過redis未授權訪問漏洞,會造成敏感信息泄露,甚至被利用直接控制服務器,其危害不言而喻。但是在實際工作中,發現一些開發人員和運維人員並不知道如何妥善配置。因此有了本文,對redis的配置,建議就是2條,一
安裝MYSQL時的一系列三大問題與三大解決方法 問題一: 問題二: 問題三: 問題一: 在安裝時候輸入 net start mysql 時候報錯爲: net不是內部或外部命令也不是可運行。 解決方法: 環境變量的問題
有時,Python發佈的程序需要被打包爲一個文件夾、甚至一個文件發佈。 目前(2020)最佳的策略是使用pyinstaller。 pyinstaller不僅支持打包整個運行環境到一個可執行文件,而且還支持加密。 但唯一的問題是,必須依賴
[Synth 8-6014] Unused sequential element cnt_reg was removed. 綜合的時候, 上面報錯,說的是 cnt這個寄存器,被綜合去掉了。 仔細看了一下代碼,原來這個寄存器是多餘的,他是一
通過線性響應理論可以證明 然後用格林函數運動方程,求解這個格林函數。
1)編碼 消息長度(short int-->2個字節) + 消息編號(short int--》2個字節) + 消息體 2)Protobuf協議文檔 (1)syntax="proto3"; (2)命名格式
一般情況下公司爲了某個團隊或者公司內部共享數據等用途來更改網站的樣式,打造獨特的品牌樣式,很多研發工程師給定的解決方案是爲他們的站點構建自定義主頁,雖然SharePoint Designer是一個強大的工具,但這裏我不推薦使用ShareP