编译装饰器
① 【angular】NgMole学习
NgMole参考手册
在模板中可用的选择器 selector 包括那些直接声明在这里的可声明对象和导入的那些 NgMole 中所导出的可声明对象。
可声明对象必须属于也 只能属于一个模块 。 如果你尝试把同一个类声明在多个模块中,那么编译器就会报错。 要注意 不能声明那些从其它模块中导入的类 。
Angular 使用 entryComponents 来启用 树震动 , 即 只编译 项目中 实际使用 的组件 ,而不是编译所有在 ngMole 中声明但从未使用的组件
这是用 ViewContainerRef.createComponent( ) 添加的动态添加的组件。将它们添加到 entryComponents 告诉脱机模板编译器编译它们并为它们创建工厂。
Angular 会自动将以下类型的组件添加到模块的 entryComponents 中:
① @ NgMole.bootstrap 列表中的组件,如动态加载 AppComponent 。
② 路由器配置中引用的组件,因为 router-outlet 也使用 ViewContainerRef.createComponent( ) 将路由组件添加到 DOM 。。
离线模板编译器 OTC 只生成实际使用的组件。如果组件不直接用于模板, OTC 不知道是否需要编译。有了 entryComponents ,你可以告诉 OTC 也编译这些组件,以便在运行时可用。 如一个列表页中点击新增按钮时,弹出的表单组件,它不在路由中,需要显示写在 entryComponents 中 。
导出具有传递性。 MoleA 可以导入 MoleB 并将其导出,这会让所有 MoleB 中的导出同样可用在导入了 MoleA 的那些模块中。
angular 中的 NgMole 是否类似 java 中的 package 呢?
通过导出的传递性,将第三方组件模块引入到具体的页面模块
Angular 系统中通过在类上添加 @Injectable 装饰器来告诉系统这个类(服务)是可注入的。当然了这仅仅只是告诉 Angular 系统这个类(服务)类是可注入的。但是这个服务可以在哪里使用,由谁提供,就得靠注入器和提供商来一起确定了。
(一) providedIn 方式:对应三个值: Type<any> 、 root 、 null
编译的时候会抛出一个警告信息,编译不过。具体怎么写,也请看原文吧。
(二) Component (组件)级注入器
本人自己看的 angular工程案例 中,使用 第二种方式 的居多(即装饰器 @Component 中的 providers 比较常见; @NgMole中 的 providers 就在 app.mole 中见过 );
关于 provider的详细介绍 也请参看原文,本人还未深入学习,后期有机会深入使用的话,再认真看看。暂时先会简单的使用!!!
@NgMole 了解一点喽,后面再看看其他装饰器: Angular装饰器介绍
② 2021年的前端框架选择 Angular vs React vs Vue
每个前端开发人员都听说过三个用于构建 Web 应用程序的框架:React、Vue.js和Angular。
React 是一个 UI 库,Angular 是一个成熟的前端框架,而 Vue.js 是一个渐进式框架。
它们几乎可以互换使用来构建前端应用程序,但它们并非 100% 相同,因此比较它们并了解它们的差异是有意义的。
每个框架都是基于组件的,并允许快速创建 UI 功能。
然而,它们都有不同的结构和架构——所以首先,我们将研究它们的架构差异以了解它们背 后的哲学。
React 不强制执行特定的项目结构,正如您从下面的官方“Hello World”示例中看到的那样,您只需几行代码即可开始使用 React。
React 可以用作 UI 库来渲染元素,而无需强制执行特定的项目结构,这就是它不是严格意义上的框架的原因。
React Elements是 React 应用程序的最小构建块。它们比 DOM 元素更强大,因为 React DOM 确保在发生变化时有效地更新它们。
组件是更大的构建块,定义了在整个应用程序中使用的独立且可重用的部分。它们接受称为 props 的输入并生成元素,然后显示给用户。
React 基于 JavaScript,但它主要与JSX (JavaScript XML)结合,这是一种语法扩展,允许您创建同时包含 HTML 和 JavaScript 的元素。
您使用 JSX 创建的任何内容也可以使用 React JavaScript API 创建,但大多数开发人员更喜欢 JSX,因为它更直观。
Vue.js 核心库只关注视图层。之所以称为渐进式框架,是因为您可以使用官方和第三方包(例如Vue Router或Vuex )扩展其功能,将其转变为实际框架。
虽然 Vue 与 MVVM(Model-View-ViewModel)模式没有严格关联,但它的设计部分受到了它的启发。使用 Vue,您将主要在 ViewModel 层上工作,以确保以允许框架呈现最新视图的方式处理应用程序数据。
Vue 的模板语法让您可以创建 View 组件,并将熟悉的 HTML 与特殊指令和功能相结合。这种模板语法是首选,即使原始 JavaScript 和 JSX 也受支持。
Vue 中的组件很小,是自包含的,并且可以在整个应用程序中重复使用。带有扩展名的单文件组件(SFC).vue包含 HTML、CSS 和 JavaScript,因此所有相关代码都位于一个文件中。
SFC 是在 Vue.js 项目中组织代码的推荐方式,尤其是大型项目。需要使用 Webpack 或 Browserify 等工具将 SFC 转换为可用的 JavaScript 代码。
在本文中,我讨论的是 Angular 2,而不是现在称为 AngularJS 的框架的第一个版本。
AngularJS,原始框架,是一个MVC(模型-视图-控制器)框架。但是在Angular 2 中,与 MV*-patterns 没有严格的关联,因为它也是基于组件的。
Angular 中的项目被组织成模块、组件和服务。每个 Angular 应用程序至少有一个根组件和一个根模块。
Angular 中的每个组件都包含一个模板、一个定义应用程序逻辑的类和元数据(装饰器)。组件的元数据告诉 Angular 在哪里可以找到创建和呈现其视图所需的构建块。
Angular 模板是用 HTML 编写的,但也可以包含带有特殊指令的Angular 模板语法,以输出反应性数据和呈现多个元素等。
组件使用 Angular 中的服务来委托业务逻辑任务,例如获取数据或验证输入。它们是 Angular 应用程序的独特部分。虽然 Angular 不强制使用它们,但强烈建议将应用程序构建为一组可以重用的不同服务。
Angular 内置于 TypeScript 中,因此建议使用它以获得最无缝的体验,但也支持纯 JavaScript。
React 是最受欢迎的 JavaScript 项目之一,在 GitHub 上拥有 16 万颗星。它由 Facebook 开发和维护,并在他们的许多项目内部使用。此外,根据BuiltWith的使用统计数据,它为超过 200 万个网站提供支持。
在三个框架中,Vue在 GitHub上的 star 数最多,有 176k。该项目由前 Google 员工 Evan You 开发和领导。据BuiltWith 称,这是开源社区中一个非常强大的独立项目,被超过 100 万个网站使用。
Angular 是由 Google 开发的,但令人惊讶的是它并没有用于他们的一些旗舰产品,例如搜索或 Youtube。它经常用于企业项目,并基于BuiltWith的数据为超过 97,000 个网站提供支持。
它是三个框架中星数最少的,在 GitHub 上有 68k 星。然而,当从 Angular 1 切换到 Angular 2 时,他们创建了一个全新的代码库,而不是继续AngularJS项目,该项目也有 59k 星。
在开发应用程序时,开源包可以为您节省宝贵的时间。不仅如此,它们通常比定制组件和封装更好,因为它们经过了实战测试。
查看可帮助您更轻松地创建新功能的现成组件、主题和其他工具的可用性非常重要。
许多前端应用程序依赖全局状态管理来存储信息,例如谁登录和其他用户设置。
最流行的 JavaScript 状态管理项目是Rex。大多数开发人员使用Rex的官方 React 绑定,这些绑定由 Rex 团队维护。
由于 React 的流行,查找输入组件和现成的元素非常容易。它们都只是在 Google 或 GitHub 上搜索即可。
React 生态系统还包括React Native,它允许您从用 React 编写的单个代码库构建原生 iOS 和 Android 应用程序。因此,React 也可以成为使用 Web 技术构建移动应用程序的绝佳选择。
React 是 MERN 堆栈的一部分,其中包含 MongoDB、ExpressJS、React 和 NodeJS。这种组合的伟大之处在于,单一语言——JavaScript——为整个应用程序提供动力。
尽管 Rex 可以在 Vue 中使用,但没有官方绑定。但这不应该让您担心,因为Vuex是专门为 Vue 应用程序制作的官方状态管理库。除了与 Vue 很好地集成之外,使用 Vue 的开发人员工具进行调试也很容易。
在 Vue 的早期,很难找到现成的组件。随着社区的发展,您可以使用各种输入组件和高级元素来加快开发速度。
对于移动应用程序开发,有一个名为Weex 的新兴项目。Weex 由阿里巴巴开发和使用,但不如 React Native 成熟和强大。更重要的是,由于该项目在中国开发和使用较多,因此很难找到英文文档和解决问题的方法。
Vue 与 Laravel 集成得很好,这就是为什么它们经常一起使用。Laravel 提供完整的JavaScript 和 CSS 脚手架,以支持在新项目中使用 Vue。
对于 Angular 中的状态管理,您可以使用NgRx项目。它的灵感来自 Rex,但它是专门为 Angular 创建的。
与 Vue 和 React 的情况一样,您可以将许多现成的组件导入到您的项目中。与 Angular 略有不同的是,Angular Material项目中有许多官方组件。这是 Google 的一个官方项目,为 Angular 应用程序提供 Material Design 组件。
您可以使用NativeScript在 Angular 中构建跨平台移动应用程序。它也支持 Vue,但 Angular 支持更成熟。
Angular 是着名的 MEAN 堆栈的一部分,它将 Angular 与 MongoDB、ExpressJS 和 NodeJS 相结合。与 MERN 堆栈类似,它的前端和后端都完全依赖 JavaScript。
Angular、React 和 Vue 都可用于开发渐进式 Web 应用程序,也称为 PWA。
PWA 不是移动应用程序,而是 Web 应用程序,智能手机用户可以将其添加为主屏幕的快捷方式,并提供类似于原生移动应用程序的外观和感觉。
您还可以为每个框架找到高级模板和预制应用程序,但 Angular 和 React 比 Vue 提供更多高级选项。
在选择框架或库时,您还需要考虑性能。
在许多情况下,您不必担心性能,尤其是在构建小型项目时。然而,项目的范围和复杂性越大,性能就会(并且将会)成为一个问题。
重要的是要注意,在 Web 性能方面,开发质量和遵循最佳实践比框架的选择更重要。
但由于存在一些性能指标和差异,我将研究它们并解释每个指标如何影响您的开发工作。
JS 框架基准测试的结果表明,它们在大多数基准测试中都表现得相当好,例如在表中创建或附加行。
正如你在上面看到的,Vue 在选择行时比 Angular 和 React 慢得多。另一方面,Angular 和 React 在交换行方面效率不高。
这些是渲染基准中唯一的实质性差异 - 在大多数情况下,不会产生明显的结果。由于选择行是比交换行更常见的功能,我想说这个基准测试将 Vue 排在第三位,仅次于 Angular 和 React 并列第一。
在内存和启动时间方面,React 和 Vue 得分很好,但 Angular 稍慢。Angular 启动一个基本脚本可能需要 150 毫秒,并且需要更多内存才能运行。
谷歌 Chrome 实验室的Perf Track显示了来自数千个网站的生产数据。这些统计数据受许多其他因素的影响,而不仅仅是选择的框架,让我们看看数字。
与 Angular 相比,Vue 和 React 网站在这个指标上的排名更高,Angular 需要更多时间来启动并向用户呈现内容。
在渲染完整页面的三个框架中,Angular 也是最慢的,只有 27% 的 Angular 网站得分在可接受的范围内。
对于所有三个框架,超过 80% 的网站都在第一次输入延迟的可接受范围内,这显示了用户可以与页面交互所需的时间。
迄今为止,最轻量级的应用程序是使用 Vue 开发的应用程序,68% 的 Vue 应用程序加载的 JavaScript 不到 1MB。另一方面,Angular 和 React 应用程序往往具有更大的代码大小。
您可以从这些数字中看到趋势,但您不应该太快得出结论。例如,对于最后一张图,可以解释为 Vue 用于开发更轻量级的应用程序,而 Angular 用于更大的项目。
统计数据可以帮助指导您做出正确的决定,但您不能使用它们来证明一个框架比另一个更快或更好。
对于更高级的应用程序,使用的前端框架应该能够执行一些提高性能并且可以更好地扩展的任务。
两项关键技术是服务器端渲染 (SSR) 和虚拟化。
React 支持使用官方ReactDOMServer包进行服务器端渲染。对于虚拟化,您可以使用名为React Virtualized的流行第三方工具。
Vue 中也支持服务器端渲染以及官方的SSR 包。此外,您还可以使用基于 Vue 构建并支持 SSR的Nuxt.js框架。
不幸的是,Vue 中的虚拟化选项并不是那么强大。在我看来,Vue Virtual Scroll List是虚拟滚动的最佳解决方案,但它有点问题,不如 React 和 Angular 的选项稳定。
Angular 拥有SSR的官方Angular Universal包,以及用于虚拟滚动和高效渲染大型列表的官方组件。
学习这些框架有多容易?
要回答这个问题,我们需要查看每个框架的复杂性及其引入的概念。
在最基本的用例中,React 是三个框架中最不复杂的。那是因为你只需要导入库,然后你就可以用几行代码开始编写你的 React 应用程序。
但是除了 Hello World 示例之外,大多数 React 应用程序都是基于组件的,而不仅仅是在页面上呈现一些元素。
一些开发人员对 React 感到奇怪或困难的一件事是,学习 JSX 是一条单行道。您也可以使用原始 JavaScript,但由于大多数 React 开发人员使用 JSX,学习它几乎是不可避免的。
这是使 React 的学习曲线变得更陡峭的主要因素,但除此之外,对于了解 JavaScript 并理解 Web 开发概念的开发人员来说,它是一个易于学习的库。
Vue 的设置比 React 稍微复杂一些。你可以将它用作一个库来定义你可以在整个 HTML 中使用的组件——但与 React 类似,这不是大多数项目的构建方式。
大多数 Vue 项目都有一个命名的根组件App.vue和一些用于显示各种内容的子组件。
说到语法,你唯一需要学习的新东西就是 Vue 的模板语法,如果你了解 HTML,这很容易掌握。基本的指令,如v-if和v-for有条件的渲染和列表的渲染,很容易理解即使是初学者。
此外,Vue 的单文件组件将所有前端代码保存在一个地方,便于组织新项目。
在我看来,Vue 是最容易学习的,因为它的简单和直观的语法。
Angular 拥有三者中最复杂的项目结构,而且由于它是一个成熟的前端框架,因此它依赖的概念更多。
除了组件,Angular 还支持模块和服务。它希望您以特定的方式编写和设计代码库,从而使您的项目在扩展时更易于维护。
至于语法,由于 Angular 最适合与 TypeScript 配合使用,因此在构建 Angular 项目时了解 TypeScript 非常重要。
与 Vue 一样,您还必须熟悉类似 HTML 的语法,以便您可以开始使用 Angular 编写新的 UI 功能。
在我看来,Angular 对于普通开发者来说是最难学的,因为它更复杂并且依赖于 TypeScript。
许多开源项目和框架逐渐被遗忘并无人维护。您是否应该担心我们在这里讨论的任何框架?
尽管我们无法完全预测会发生什么,但正在进行的开发工作是这些项目 健康 状况的良好指标。人气和增长也是预测项目寿命的重要指标,所以让我们来看看每个框架。
React v17.0已经发布,但令人惊讶的是,它没有为开发人员提供任何新功能。
主要的变化是这个新版本可以更容易地升级 React 本身。您可以将 React 的某些部分从旧版本升级到新版本,而无需升级整个项目。
如果您的应用程序依赖于随新版本更改或弃用的功能,您可以保留旧版本以保持此功能有效。此更新使 React 成为一个很好的长期选择,因为它可以更轻松地与新版本保持同步。
React 的每周 npm 下载量自去年以来增长了 44% 。从绝对数量来看,它仍然是三个项目中下载量最大的。
Vue 3 已于2020 年 9 月发布,它解决了 Vue 2 在大型项目中存在的许多严重问题。它引入了受React Hooks启发的Composition API,可以更轻松地跨组件重用逻辑。
整个项目用 TypeScript 重写,提高了新 Vue 项目对 TypeScript 的支持,同时也使项目更易于维护。
Vue 3 是一个急需的升级,使 Vue 更适合大型项目。
Vue 的每周下载量自去年以来增长了 87%,使 Vue 成为相对而言增长最快的框架。如果 Vue 能够保持这种增长速度,那么它肯定会很快超过 Angular。
Angular 最近推出了Ivy 编译器。它减少了构建时间,优化了资产,允许更快的测试,并总体上改善了开发人员的体验。
Angular 团队每年发布两次重大更新,其中可能包含新功能,或者只是让框架跟上新浏览器版本的速度。
自去年以来,Angular 的每周下载量增长了约 50% ,因此它仍然是一个受欢迎的项目。
Angular、React 和 Vue 都处于非常活跃的开发阶段。他们定期发布新版本并维护现有版本。由于在每种情况下当前的支持水平都很高,因此您可以安全地使用这些框架中的任何一个。
需要注意的是,Angular 的增长没有以前那么快,而 Vue—— 尽管它是最近开始的——似乎增长了很多。
如前所述,我们无法预测哪些框架会长期保持相关性,但每个项目背后都有一个伟大的社区,并且在不断发展。
我这篇文章的目标是解释架构差异,分解每个框架的优点和缺点,并在适用的地方进行比较。
在进入一个新框架之前,有几件事情需要考虑。
首先,在选择新技术时,您团队的经验可能是一个决定性因素。
同样,您必须考虑您所在地区可用的人才,以便您可以为您的项目聘请开发人员。
最后,当涉及到项目本身时,复杂性和范围也会影响您对框架的选择。
通过考虑所有关键差异,我希望您可以决定哪个是最适合您的目标和需求的前端框架。
(本文由闻数起舞翻译自Aris Pattakos的文章《Angular vs React vs Vue 2021》,转载请注明出处,原文链接:https://athemes.com/guides/angular-vs-react-vs-vue/)
③ 如何学习python
1、Python 介绍
学习一门新的语言之前,首先简单了解下这门语言的背景。Python 是一种面向对象的解释型计算机程序设计语言,由荷兰人 Guido van Rossum 于 1989 年发明,第一个公开发行版发行于 1991 年。Python 在设计上坚持了清晰划一的风格,这使得 Python 成为一门易读、易维护,并且被大量用户所欢迎的、用途广泛的语言。Python 具有丰富和强大的库。它常被昵称为胶水语言,能够把用其他语言制作的各种模块(尤其是 C/C++)很轻松地联结在一起。
2、Python 技术浪潮
IT行业热门技术,更新换代非常的快,技术的浪潮一波接着一波,最初的浪潮无疑是桌面时代,使用 C# 搭建桌面应用开始崭露头角,MFC 还是计算机科学专业必学会的东西。接着就是以网站搭建为应用的背景,PHP,Ruby 等语言为主的。再到近几年非常火热的以移动开发为应用背景,Java(Android 开发)或者 OC(iOS 开发)语言为主。很明显如今的浪潮就是以大数据和机器学习为应用背景,Python 语言为主。站在风尖浪口,猪都可以飞的起来。抓住这波技术浪潮,对于从事 IT 行业的人员来说有莫大的帮助。
3、Python 学习
学习一项新的技术,起步时最重要的是什么?就是快速入门。学习任何一个学科的知识时,都有一个非常重要的概念:最少必要知识。当需要获得某项技能的时候,一定要想办法在最短的时间里弄清楚都有哪些最少必要知识,然后迅速掌握它们。
对于快速入门 python 来说最少必要知识,有以下几点。
(1) Python 基础语法
找一本浅显易懂,例子比较好的教程,从头到尾看下去。不要看很多本,专注于一本。把里面的例程都手打一遍,搞懂为什么。推荐去看《简明python教程》,非常好的一本 Python 入门书籍。
(2)Python 实际项目
等你对 Python 的语法有了初步的认识,就可以去找些 Python 实际项目来练习。对于任何计算机编程语言来说,以实际项目为出发点,来学习新的技术,是非常高效的学习方式。在练习的过程中你会遇到各种各样的问题:基础的语法问题(关键字不懂的拼写),代码毫无逻辑,自己的思路无法用代码表达出来等等。这时候针对出现的问题,找到对应解决办法,比如,你可以重新查看书本上的知识(关于基础语法问题),可以通过谷歌搜索碰到的编译错误(编辑器提示的错误),学习模仿别人已有的代码(写不出代码)等等。已实际项目来驱动学习,会让你成长非常的快。Python 实际项目网上非常的多,大家可以自己去搜索下。合理利用网络资源,不要意味的只做伸手党。
(3) Python 的学习规划
当你把上面两点做好以后,你就已经入门了 Python,接下来就是规划好自己的以后的学习规划。能找到一个已经会 Python 的人。问他一点学习规划的建议,然后在遇到卡壳的地方找他指点。这样会事半功倍。但是,要学会搜索,学会如何更好地提问,没人会愿意回答显而易见的问题。当然如果你身边没有人会 Python,也可以在网上搜索相应的资料。
Python 可以做的事非常的多,比如:Python 可以做日常任务,比如自动备份你的MP3;可以做网站,很多着名的网站像知乎、YouTube 就是 Python 写的;可以做网络游戏的后台,很多在线游戏的后台都是 Python 开发的。每个人都有自己感兴趣的方向,有的对网站开发比较感兴趣,有的对数据处理感兴趣,有的对后台感兴趣。所以你们可以根据自己感兴趣的方向,网上搜索相关资料,加以深入的学习,规划好自己未来的方向。只要坚持,你就能精通 Python,成为未来抢手的人才。
④ Python为什么能扩展
Python 具有高可扩展性,存在许多使用 C 语言或 Fortran 编写扩展的方法。必要时,Python 代码可以直接将这些扩展作为子例程来调用。这部分讨论用于构建扩展的一些主要编译器(绝对不是完整列表)。
相关推荐:《Python基础教程》
Cython
Cython(不同于 CPython)既是指一种语言,也是指一种编译器。Cython 语言是添加了 C 语言语法的 Python 语言的超集。Cython 可以在代码段或完整函数中显式释放 GIL。变量和类属性上的 C 类型声明以及对 C 函数的调用都使用 C 语法。其余部分代码则使用 Python 语法。通过这个混合的 Cython 代码,Cython 编译器可生成高效的 C 代码。任何定期优化的 C/C++ 编译器都可以编译此 C 代码,从而高度优化扩展的运行时代码,性能接近于原生的 C 代码性能。
Numba
Numba 是一个动态、即时 (JIT) 且可感知 NumPy 的 Python 编译器。Numba 使用 LLVM 编译器基础架构,生成优化的机器代码和从 Python 调用代码的包装器。与 Cython 不同,编码使用常规的 Python 语言。Numba 可读取来自装饰器中所嵌入注释的类型信息,并优化代码。对于使用 NumPy 数据结构的程序,比如数组以及许多数学函数,它可以实现与 C 或 Fortran 语言类似的性能。NumPy 对线性代数和矩阵函数使用硬件加速,利用 LAPACK 和 BLAS 提供额外加速,大大提升了性能,参见 IBM 博客文章C、Julia、Python、Numba 和 Cython 在 LU 因式分解方面的速度比较。
除 CPU 以外,Numba 还能够使用 GP-GPU 后端。Anaconda, Inc. 是 Python 某个主要发行版的幕后公司,该公司还开发了 Numba 和商业版的 Numba Pro。
Fortran to Python Interface Generator
Fortran to Python Interface Generator (F2Py) 起初为一个独立的程序包,现在包含在 NumPy 中。F2Py 支持 Python 调用以 Fortran 编写的数值例程,就好像它们是另一个 Python 模块一样。因为 Python 解释器无法理解 Fortran 源代码,所以 F2Py 以动态库文件格式将 Fortran 编译为本机代码,这是一种共享对象,包含具有 Python 模块接口的函数。因此,Python 可以直接将这些函数作为子例程来调用,以原生 Fortran 代码的速度和性能来执行。
⑤ Category(类别)是怎样的
Category(类别)是一种不需要子类化就可以让能动态的给已经存在的类增加方法的强有力的机制。新增的方法是在编译期增加的,这些方法执行的时候和被扩展的类的其它方法是一样的。它可能与装饰器设计模式的定义稍微有点不同,因为Category(类别)不会保存被扩展类的引用。
⑥ 如何在 TypeScript 中使用装饰器
TypeScript 是 JavaScript 语言的扩展,它使用 JavaScript 的运行时和编译时类型检查器。
这种组合允许开发人员使用完整的 JavaScript 生态系统和语言功能,同时,还可以在其之上添加可选的静态类型检查、枚举、类和接口。这些额外功能之一是装饰器的支持。
装饰器是一种装饰类成员或类本身的方法,具有额外的功能。
当我们将装饰器应用于类或类成员时,我们实际上是在调用一个函数,该函数将接收被装饰内容的详细信息,然后,装饰器实现将能够动态转换代码,添加额外的功能,并且 减少样板代码。
它们是在 TypeScript 中进行元编程的一种方式,TypeScript 是一种编程技术,使程序员能够创建使用来自应用程序本身的其他代码作为数据的代码。
本教程将分享如何在 TypeScript 中为类和类成员创建自己的装饰器,以及如何使用它们。
它将引导我们完成不同的代码示例,我们可以在自己的 TypeScript 环境或 TypeScript Playground(一个允许我们直接在浏览器中编写 TypeScript 的在线环境)中遵循这些示例。
准备工作
要完成本教程实例,我们需要做如下准备:
在 TypeScript 中启用装饰器支持
目前,装饰器在 TypeScript 中仍然是一个实验性功能,因此,必须先启用它。在本节中,我们将了解如何在 TypeScript 中启用装饰器,具体取决于您使用 TypeScript 的方式。
TypeScript 编译器 CLI
要在使用 TypeScript Compiler CLI (tsc) 时启用装饰器支持,唯一需要的额外步骤是传递一个附加标志 --experimentalDecorators:
tsconfig.json
在具有 tsconfig.json 文件的项目中工作时,要启用实验性装饰器,我们必须将实验性装饰器属性添加到 compilerOptions 对象:
在 TypeScript Playground 中,装饰器默认启用。
使用装饰器语法
在本节中,我们将在 TypeScript 类中应用装饰器。
在 TypeScript 中,我们可以使用特殊语法 @expression 创建装饰器,其中 expression 是一个函数,将在运行时自动调用,其中包含有关装饰器目标的详细信息。
装饰器的目标取决于我们添加它们的位置。 目前,装饰器可以添加到类的以下组件中:
例如,假设我们有一个名为 seal 的装饰器,它在类中调用 Object.seal。 要使用我们的装饰器,我们可以编写以下内容:
这同样适用于所有其他类型的装饰器:
要添加多个装饰器,请将它们一个接一个地添加在一起:
在 TypeScript 中创建类装饰器
在本节中,我们将完成在 TypeScript 中创建类装饰器的步骤。
对于名为 @decoratorA 的装饰器,我们告诉 TypeScript 它应该调用函数 decoratorA。 将调用 decoratorA 函数,其中包含有关如何在代码中使用装饰器的详细信息。
要创建自己的装饰器,我们必须创建一个与装饰器同名的函数。 也就是说,要创建您在上一节中看到的密封类装饰器,您必须创建一个接收一组特定参数的密封函数。 让我们这样做:
传递给装饰器的参数将取决于装饰器的使用位置。第一个参数通常称为目标。
然后,在密封函数中,在目标(即类构造函数)以及它们的原型上调用 Object.seal。当这样做时,不能将新属性添加到类构造函数或其属性中,并且现有属性将被标记为不可配置。
重要的是要记住,目前在使用装饰器时无法扩展目标的 TypeScript 类型。这意味着,例如,你无法使用装饰器将新字段添加到类并使其成为类型安全的。
如果在密封类装饰器中返回了一个值,该值将成为该类的新构造函数。如果想完全覆盖类构造函数,这很有用。
已经创建了第一个装饰器,并将它与一个类一起使用。
接下来,我们将学习如何创建装饰器工厂。
创建装饰器工厂
有时,我们需要在应用装饰器时将其他选项传递给装饰器,为此,我们必须使用装饰器工厂。
在这里,我们将学习如何创建和使用这些工厂。
装饰器工厂是返回另一个函数的函数。他们收到这个名字是因为他们不是装饰器实现本身。
相反,它们返回另一个负责实现装饰器的函数并充当包装函数。通过允许客户端代码在使用装饰器时将选项传递给装饰器,它们在使装饰器可定制方面很有用。
假设,有一个名为 decoratorA 的类装饰器,并且,我们想添加一个可以在调用装饰器时设置的选项,例如,布尔标志,可以通过编写类似于以下的装饰器工厂来实现此目的:
在这里,decoratorA 函数返回另一个带有装饰器实现的函数。 注意,装饰器工厂如何接收一个布尔标志作为它的唯一参数:
我们可以在使用装饰器时传递此参数的值。
请参阅以下示例中突出显示的代码:
在这里,当我们使用 decoratorA 装饰器时,将调用装饰器工厂,并将 someBooleanFlag 参数设置为 true。
然后,装饰器实现本身将运行。 这允许我们根据使用方式更改装饰器的行为,从而,使我们的装饰器易于自定义和通过应用程序重用。
请注意,我们需要传递装饰器工厂预期的所有参数。 如果,我们只是应用装饰器而不传递任何参数,如下例所示:
TypeScript 编译器会给你两个错误,这可能会因装饰器的类型而异。 对于类装饰器,错误是 1238 和 1240:
我们刚刚创建了一个能够接收参数并根据这些参数更改其行为的装饰器工厂。
在下一步中,我们将学习如何创建属性装饰器。
创建属性装饰器
类属性是另一个可以使用装饰器的地方,在这里,我们将了解如何创建它们。
任何属性装饰器都接收以下参数:
目前,没有办法获取属性描述符作为参数。 这是由于 TypeScript 中属性装饰器的初始化方式。
这是一个装饰器函数,它将成员的名称打印到控制台:
当我们运行上面的 TypeScript 代码时,你会在控制台中看到如下打印:
我们可以使用属性装饰器来覆盖被装饰的属性。这可以通过Object.defineProperty与属性的新 setter 和 getter 一起使用来完成。
让我们看看如何创建一个名为 的装饰器allowlist,它只允许将属性设置为静态允许列表中存在的值:
首先,我们要在代码顶部创建一个静态许可名单:
然后,我们创建一个属性装饰器:
请注意,我们如何使用 any 作为目标的类型:
对于属性装饰器来说,目标参数的类型可以是类的构造函数,也可以是类的原型,在这种情况下使用any比较容易。
在装饰器实现的第一行中,我们将被装饰的属性的当前值存储到 currentValue 变量中:
对于静态属性,这将设置为其默认值(如果有)。
对于非静态属性,这将始终未定义。 这是因为在运行时,在编译的 JavaScript 代码中,装饰器在实例属性设置为其默认值之前运行。
然后,我们将使用 Object.defineProperty 覆盖该属性:
Object.defineProperty 调用有一个 getter 和一个 setter。 getter 返回存储在 currentValue 变量中的值。
如果 currentVariable 在允许列表中,setter 会将其值设置为 newValue。
让我们使用您刚刚编写的装饰器。 创建以下 Person 类:
我们现在将创建类的新实例,并测试设置并获取name实例属性:
运行代码,我们应该看到以下输出:
该值永远不会设置为 Peter,因为 Peter 不在允许列表中。
如果我们想让代码更具可重用性,允许在应用装饰器时设置允许列表,该怎么办? 这是装饰器工厂的一个很好的用例。
让我们通过 allowlistOnly 装饰器变成装饰器工厂来做到这一点。
在这里,我们将之前的实现包装到另一个函数中,即装饰器工厂。 装饰器工厂接收一个名为允许列表的参数,它是一个字符串数组。
现在,要使用的装饰器,我们必须通过许可名单,如以下突出显示的代码所示:
尝试运行与之前编写的代码类似的代码,但有新的更改:
输出如下:
显示它按预期工作,person.name 永远不会设置为 Peter,因为 Peter 不在给定的白名单中。
现在,我们已经使用普通装饰器函数和装饰器工厂创建了第一个属性装饰器,是时候看看如何为类访问器创建装饰器了。
创建访问器装饰器
在这里,我们将了解装饰类访问器。
就像属性装饰器一样,访问器中使用的装饰器接收以下参数:
但与属性装饰器不同的是,它还接收第三个参数,即访问器成员的属性描述符。
鉴于 Property Descriptors 包含特定成员的 setter 和 getter,访问器装饰器只能应用于单个成员的 setter 或 getter,而不能同时应用于两者。
如果我们从访问器装饰器返回一个值,该值将成为 getter 和 setter 成员的访问器的新属性描述符。
下面是一个可用于更改 getter/setter 访问器的可枚举标志的装饰器示例:
请注意示例中,我们是如何使用装饰器工厂的。 这允许我们在调用装饰器时指定可枚举标志。
以下是如何使用装饰器:
访问器装饰器类似于属性装饰器。 唯一的区别是它们接收带有属性描述符的第三个参数。 现在,我们已经创建了第一个访问器装饰器。
接下来,我们将学习如何创建方法装饰器。
创建方法装饰器
在这里,我们将学习如何使用方法装饰器。
方法装饰器的实现与创建访问器装饰器的方式非常相似。 传递给装饰器实现的参数与传递给访问器装饰器的参数相同。
让我们重用之前创建的同一个可枚举装饰器,但这次是在以下 Person 类的 getFullName 方法中:
如果我们从方法装饰器返回一个值,该值将成为该方法的新属性描述符。
让我们创建一个deprecated的装饰器,它在使用该方法时将传递的消息打印到控制台,记录一条消息说该方法已被弃用:
在这里,我们正在使用装饰器工厂创建装饰器。 这个装饰器工厂接收一个字符串类型的参数,这是弃用的原因,如下面突出显示的部分所示:
deprecationReason 将在稍后将弃用消息记录到控制台时使用。在不推荐使用装饰器的实现中,我们正在返回一个值。当我们从方法装饰器返回值时,该值将覆盖该成员的属性描述符。
我们正在利用这一点为装饰类方法添加一个吸气剂。这样,我们就可以更改方法本身的实现。
但是为什么不直接使用 Object.defineProperty 而不是为方法返回一个新的属性装饰器呢?这是必要的,因为,我们需要访问 this 的值,对于非静态类方法,它绑定到类实例。
如果,我们直接使用 Object.defineProperty ,将无法检索 this 的值,并且如果该方法以任何方式使用 this ,则当从装饰器实现中运行包装的方法时,装饰器会破坏我们的代码。
在这样情况下,getter 本身的 this 值绑定到非静态方法的类实例,并绑定到静态方法的类构造函数。
然后,在你的 getter 中创建一个本地包装函数,称为 wrapperFn,此函数使用 console.warn 将消息记录到控制台,传递从装饰器工厂收到的 deprecationReason,然后使用 propertyDescriptor.value 调用原始方法。
apply(this, args),以这种方式调用原始方法,并将其 this 值正确绑定到类实例,以防它是非静态方法。
然后,我们将使用 defineProperty 覆盖类中方法的值。这就像一种记忆机制,因为对同一方法的多次调用将不再调用 getter,而是直接调用 wrapperFn。
我们现在正在使用 Object.defineProperty 将类中的成员设置为将wrapperFn 作为其值。
让我们使用已弃用的装饰器:
在这里,我们创建了一个具有两个属性的 TestClass:一个是静态的,一个是非静态的。 我们还创建了两种方法:一种是静态的,一种是非静态的。
然后,我们将已弃用的装饰器应用于这两种方法。 运行代码时,控制台中会出现以下内容:
这表明这两种方法都使用了包装函数正确包装,该函数将一条消息记录到控制台并说明弃用原因。
你现在已经使用 TypeScript 创建了你的第一个方法装饰器。
接下来,我们将学习如何创建 TypeScript 支持的最后一个装饰器类型,即参数装饰器。
创建参数装饰器
参数装饰器可以用在类方法的参数中。
在这里,我们将学习如何创建一个与参数一起使用的装饰器函数,
接收以下参数:
方法参数列表中参数的索引。
无法更改与参数本身相关的任何内容,因此,此类装饰器仅对观察参数使用本身有用(除非您使用更高级的东西,例如反射元数据)。
这是一个装饰器的示例,它打印被装饰的参数的索引以及方法名称:
然后,你可以像这样使用你的参数装饰器:
运行上述代码应在控制台中显示以下内容:
我们现在已经创建并执行了一个参数装饰器,并打印出返回装饰参数索引的结果。
总结
在本教程中,我们已经实现了 TypeScript 支持的所有装饰器,将它们与类一起使用,并了解了它们之间的区别。
现在可以开始编写自己的装饰器来减少代码库中的样板代码,或者更加自信地使用带有库(例如 Mobx)的装饰器。
以上就是我跟你分享的全部内容,如果你觉得有用,请记得分享给你身边的朋友,也许能够帮助到他。
⑦ Python课程内容都学习什么啊
贺圣军Python轻松入门到项目实战(经典完整版)(超清视频)网络网盘
链接: https://pan..com/s/1C9k1o65FuQKNe68L3xEx3w
若资源有问题欢迎追问~
⑧ 推荐 8 个炫酷的 Python 装饰器
文章:Python数据分析实例
00
前言
Python 编程语言的一大优点是它把所有功能都打包到一个小包中,这些功能非常有用。
许多特性可以完全改变 Python 代码的功能,这使得该语言更加灵活。如果使用得当,其中一些功能可以有效缩短编写程序所需的时间。
实现这些目标的一个很好的例子是 Python 的装饰器。
00 装饰器
装饰器(decorators)是一个可以用于改变一个 Python 函数对象行为的函数。它们可以应用于类和函数,可以做很多非常有趣的事情!
装饰器可以用来缩短代码、加速代码并彻底改变代码在 Python 中的行为方式。
不用说,这当然可以派上用场!今天我想炫耀一些我认为值得一试的装饰器。
有很多装饰器,但我选择了一些我认为具有最酷功能的装饰器。
01 @lru_cache
此列表中的第一个装饰器来自 functools 模块。
该模块包含在标准库中,非常易于使用。它还包含比这个装饰器更酷的功能,但这个装饰器肯定是我最喜欢的。
此装饰器可用于使用缓存加速函数的连续运行。当然,这应该在使用时记住一些关于缓存的注意事项,但在通用使用情况下,大多数时候这个装饰器是值得使用的。
能够用一个简单的装饰器来加速代码是非常棒的。
可以从这样的装饰器中受益的函数的一个很好的例子是递归函数,例如计算阶乘的函数:
递归在计算时间上可能非常困难,但添加此装饰器有助于显着加快此函数的连续运行速度。
现在每当我们运行这个函数时,前几个阶乘计算将被保存到缓存中。
因此,下次我们调用该函数时,我们只需要计算我们之前使用的阶乘之后的阶乘。
当然,并不是所有的阶乘计算都会被保存,但是很容易理解为什么这个装饰器的一个很好的应用程序来加速一些自然很慢的代码。
02 @jit
JIT 是即时编译(Just In Time)的缩写。通常每当我们在 Python 中运行一些代码时,发生的第一件事就是编译。
这种编译会产生一些开销,因为类型被分配了内存,并存储为未分配但已命名的别名。使用即时编译,我们在执行时才进行编译。
在很多方面,我们可以将其视为类似于并行计算的东西,其中 Python 解释器同时处理两件事以节省一些时间。
Numba JIT 编译器因将这一概念提供到 Python 中而闻名。与@lru_cache 类似,可以非常轻松地调用此装饰器,并立即提高代码的性能。Numba 包提供了 jit 装饰器,它使运行更密集的软件变得更加容易,而不必进入 C。
以下案例使用@jit 装饰器加速蒙特卡洛方法计算。
03 @do_twice
do_twice 装饰器的功能与它的名字差不多。此装饰器可用于通过一次调用运行两次函数。这当然有一些用途,我发现它对调试特别有用。
它可以用于测量两个不同迭代的性能。以 Functools 为例,我们可以让一个函数运行两次,以检查是否有改进。该函数由 Python 中的装饰器模块提供,该模块位于标准库中。
04 @count_calls
count_calls 装饰器可用于提供有关函数在软件中使用多少次的信息。
像 do_twice 一样,这当然可以在调试时派上用场。
当添加到给定的函数时,我们将收到一个输出,告诉我们该函数每次运行时已经运行了多少次。这个装饰器也在标准库的装饰器模块中。
05 @dataclass
为了节省编写类的时间,我一直使用的最好的装饰器之一是@dataclass 装饰器。
这个装饰器可用于快速编写类中常见的标准方法,这些方法通常会在我们编写的类中找到。
这个装饰器来自 dataclass 模块。这个模块也在标准库中,所以不需要 PIP 来尝试这个例子!
这段代码将自动创建一个初始化函数 init,其中包含填充类中数据所需的位置参数。
它们也将自动提供给 self,因此无需编写一个很长的函数来将一些数据参数放入类中。
06 @singleton
为了理解单例装饰器的用途,我们首先需要了解单例(singleton)是什么。从某种意义上说,单例是全局变量类型的一个版本。
这意味着类型被定义为只存在一次。尽管这些在 C++ 等语言中很常见,但在 Python 中却很少见到。使用单例,我们可以创建一个只使用一次的类并改变类,而不是通过初始化来构造新的类型。
通常,单例装饰器是由用户自己编写的,实际上并不是导入的。
这是因为单例仍然是对我们单例装饰器中提供的模板的引用。我们可以命名一个单例函数并编写一个包装器,以便在我们的类上使用这个装饰器:
另一种方法是使用元类!
07 @use_unit
在科学计算中经常派上用场的一种装饰器是 @use_unit 装饰器。
此装饰器可用于更改返回结果的表示单位。这对于那些不想在数据中添加度量单位但仍希望人们知道这些单位是什么的人很有用。
这个装饰器也不是在任何模块中真正可用,但它是非常常见的,对科学应用程序非常有用。
08 @singledispatch
Functools 凭借非常有用的@singledispatch 装饰器再次在此列表中脱颖而出。
单调度是一种编程技术,在许多编程语言中都很常见,因为它是一种非常棒的编程方式。虽然我更喜欢多调度,但我认为单调度可以在很多方面扮演相同的角色。
这个装饰器使得在 Python 中使用多类型数据变得更加容易, 尤其当我们希望通过同一方法传递多种类型数据时,情况更是如此。
⑨ TypeScript基础入门之装饰器(三)
继续上篇文章[ TypeScript基础入门之装饰器(二) ]
Accessor Decorator在访问器声明之前声明。 访问器装饰器应用于访问器的属性描述符,可用于观察,修改或替换访问者的定义。 访问器装饰器不能在声明文件中使用,也不能在任何其他环境上下文中使用(例如在声明类中)。
访问器装饰器的表达式将在运行时作为函数调用,具有以下三个参数:
如果访问器装饰器返回一个值,它将用作该成员的属性描述符。
以下是应用于Point类成员的访问器装饰器( @configurable )的示例:
我们可以使用以下函数声明定义@configurable装饰器:
Property Decorator在属性声明之前声明。 属性修饰器不能在声明文件中使用,也不能在任何其他环境上下文中使用(例如在声明类中)。
属性装饰器的表达式将在运行时作为函数调用,具有以下两个参数:
我们可以使用此信息来记录有关属性的元数据,如以下示例所示:
然后我们可以使用以下函数声明定义@format装饰器和getFormat函数:
这里的 @format ("Hello,%s")装饰器是一个装饰工厂。 当调用 @format ("Hello,%s")时,它会使用reflect-metadata库中的Reflect.metadata函数为该属性添加元数据条目。 调用getFormat时,它会读取格式的元数据值。
注意此示例需要reflect-metadata库。 有关reflect-metadata库的更多信息,请参阅元数据。
参数装饰器在参数声明之前声明。 参数装饰器应用于类构造函数或方法声明的函数。 参数装饰器不能用于声明文件,重载或任何其他环境上下文(例如声明类中)。
参数装饰器的表达式将在运行时作为函数调用,具有以下三个参数:
将忽略参数装饰器的返回值。
以下是应用于Greeter类成员参数的参数装饰器( @required )的示例:
然后我们可以使用以下函数声明定义@required和@validate装饰器:
@required装饰器添加一个元数据条目,根据需要标记参数。 然后,@validate装饰器将现有的greet方法包装在一个函数中,该函数在调用原始方法之前验证参数。
一些示例使用reflect-metadata库,它为实验元数据API添加了polyfill。 该库尚未成为ECMAScript(JavaScript)标准的一部分。 但是,一旦装饰器被正式采用为ECMAScript标准的一部分,这些扩展将被提议采用。
您可以通过npm安装此库:
TypeScript包含实验支持,用于为具有装饰器的声明发出某些类型的元数据。 要启用此实验性支持,必须在命令行或tsconfig.json中设置emitDecoratorMetadata编译器选
命令行:
tsconfig.json:
启用后,只要导入了reflect-metadata库,就会在运行时公开其他设计时类型信息。
我们可以在以下示例中看到这一点:
TypeScript编译器将使用@ Reflect.metadata装饰器注入设计时类型信息。 你可以认为它相当于以下TypeScript:
⑩ vue-property-decorator的简单介绍,一看就会
参考: https://github.com/kaorun343/vue-property-decorator
怎么使vue支持ts写法呢,我们需要用到 vue-property-decorator, 这个组件完全依赖于 vue-class-component .
首先安装: npm i -D vue-property-decorator
@Component 装饰器可以接收一个对象作为参数,可以在对象中声明 components ,filters,directives 等未提供装饰器的选项,也可以声明 computed,watch 等
registerHooks: 除了上面介绍的将beforeRouteLeave放在Component中之外,还可以全局注册,就是registerHooks
2.@Prop(options: (PropOptions | Constructor[] | Constructor) = {})
@Prop 装饰器接收一个参数,这个参数可以有三种写法:
注意:属性的ts类型后面需要加上 undefined 类型;或者在属性名后面加上!,表示 非null 和 非undefined
的断言,否则编译器会给出错误提示;
@PropSync 装饰器与 @prop 用法类似,二者的区别在于:
注意,使用PropSync的时候是要在父组件配合.sync使用的
@Model 装饰器允许我们在一个组件上自定义 v-model ,接收两个参数:
注意,有看不懂的,可以去看下vue官网文档, https://cn.vuejs.org/v2/api/#model
@Watch 装饰器接收两个参数:
发生在 beforeCreate 勾子之后, created 勾子之前
@Ref 装饰器接收一个可选参数,用来指向元素或子组件的引用信息。如果没有提供这个参数,会使用装饰器后面的属性名充当参数
@Provide(key?: string | symbol) / @Inject(options?: { from?: InjectKey, default?: any } | InjectKey)` decorator
提供/注入装饰器,
key可以为string或者 symbol类型,
相同点:Provide/ProvideReactive提供的数据,在内部组件使用Inject/InjectReactive都可取到 不同点:
如果提供( ProvideReactive )的值被父组件修改,则子组件可以使用 InjectReactive 捕获此修改。
demo地址: https://github.com/slailcp/vue-cli3/tree/master/src/pc-project/views/manage