用Typescript如火如荼地进行angular.js
目录
介绍
设置环境
将指令翻译成惯用的Typescript
翻译服务
翻译值提供者
翻译控制器
使tsconfig.json更严格
离开angular.js边界
结论
本文介绍如何迁移旧的angular.js项目以使用typescript
介绍
Typescript开始越来越受欢迎,因为静态类型提供了它的好处。尽管如此,一些参与使用angular.js支持项目的开发人员可能会因缺乏社区提供使用angular.js和typescript的说明而陷入困境。本文将尽力填补这一空白。
我们的战略涉及在每个开发阶段输出工作产品。因此,在现实生活中,可以逐步过渡到typescript,从而不会损害开发团队必须达到的业务目标。
这篇文章将包含一些参考代码片段,但是如果你想更深入地学习这个主题,我建议你跟随github 项目,这是我已经翻译成typescript的现有项目的一个分支。
设置环境
首先,我们需要安装以下依赖项:
- typescript
- gulp-typescript——为了执行各自的gulp任务
- @types/angular将为angular.js内部添加强类型
接下来,我们在项目的根目录中创建tsconfig.json,如下所示:
{"compilerOptions": {"allowJs": true,"module": "none","target": "es5","types": ["angular"]},"include": ["./src/**/*.ts"]
}
我们将模块系统指定为' none',因为我们将解决模块依赖关系的工作留给angular.js,而不是像webpack这样的模块解析器。
另外,请注意我们指定类型的部分类型,例如@types/angular。
目标es5允许我们不要创建涉及babel.js的苛刻的转换piplines。
现在让我们在现有文件中添加一个gulp任务:
var ts = require('gulp-typescript');
var tsProject = ts.createProject("tsconfig.json");//Compile all typescript files into javascript
gulp.task('ts-build', function() {return gulp.src(['src/**/*.ts']).pipe(tsProject()).pipe(gulp.dest("src/"));
});
现在我们可以为现有的任务调用我们的任务:
gulp.task('usemin', ['inject-templates', 'ts-build'], function() {
现在我们已经建立了自己的环境并准备好了。此外,一切仍然正常,并准备发货。
将指令翻译成惯用的Typescript
策略是从自治单位开始翻译,并依靠已经翻译的项目继续其他单位,这样您就可以获得静态类型的好处。您还可以在任意点指定您的所有非翻译依赖类型作为转换,但在我看来,这会削弱强类型的好处,并且我建议从指令和服务开始,这些指令和服务作为您的angur.js应用程序的基础。
对于指令,您可以将.js扩展名重命名为.ts,但仍然可以利用angular.js类型和您在下面的指令中定义的类型系统:
class NgEnterDirective implements ng.IDirective {public link = (scope : any, element : JQLite, attrs : ng.IAttributes) => {element.bind("keydown keypress", (event) => {if(event.which === 13) {scope.$apply(function(){scope.$eval(attrs.ngEnter);});event.preventDefault();}});}public static Factory(): ng.IDirectiveFactory {return () => new NgEnterDirective();}
}angular.module('app.core').directive('ngEnter', NgEnterDirective.Factory());
翻译服务
让我们来看看在我们的案例研究应用程序中的ShowService:
class Actor {name: stringcharacter: string
}class Show {id: numberoriginal_name: stringcast: Actor[]genres: string[]
}class TvServiceResponse {results: Show[]
}/** Contains a service to communicate with the TRACK TV API*/
class ShowService {static $inject = ["$http", "$log", "moment"]constructor(private $http : ng.IHttpService,private $log : ng.ILogService,private moment : any) {return this;}private API_KEY : string = '87de9079e74c828116acce677f6f255b'private BASE_URL : string = 'http://api.themoviedb.org/3'private makeRequest = (url : string, params : any) : any => {let requestUrl = `${this.BASE_URL}/${url}?api_key=${this.API_KEY}`;angular.forEach(params, function(value, key){requestUrl = `${requestUrl}&${key}=${value}`;});return this.$http({'url': requestUrl,'method': 'GET','headers': {'Content-Type': 'application/json'},'cache': true}).then((response) => {return response.data;}).catch(this.dataServiceError);}getPremieres = () => {//Get first day of the current monthlet date = new Date();date.setDate(1);return this.makeRequest('discover/tv', {'first_air_date.gte': this.moment(date), append_to_response: 'genres'}).then((data : TvServiceResponse) => {return data.results;});}get = (id : number) => {return this.makeRequest(`tv/${id}`, {});}getCast = (id : number) => {return this.makeRequest(`tv/${id}/credits`, {});}search = (query : string) => {return this.makeRequest('search/tv', {query: query}).then((data : TvServiceResponse) => {return data.results;});}getPopular = () => {return this.makeRequest('tv/popular', {}).then((data : TvServiceResponse) => {return data.results;});}private dataServiceError = (errorResponse : string) => {this.$log.error('XHR Failed for ShowService');this.$log.error(errorResponse);return errorResponse;}
}angular.module('app.services').factory('ShowService', ShowService);
在这一点上,不仅值得一提的是我们如何使用我们的DTO来确保我们的程序正常工作,还有我们如何利用ES6功能,如箭头函数或字符串插值。
这里的诀窍是,我们在tsconfig.json中指定的typescript会转换为ES5 。
翻译值提供者
另一个自治部分的翻译看起来很简单:
class PageValues { title : stringdescription : stringloading : boolean
}angular.module('app.core').value('PageValues', PageValues);
翻译控制器
在转换的这个阶段,我们可以将强类型依赖项注入控制器并进行转换。
这是一个例子:
class SearchController {query: string;shows: any[];loading: boolean;setSearch = () => {const query = encodeURI(this.query);this.$location.path(`/search/${query}`);}performSearch = (query : string) => {this.loading = true;this.ShowService.search(query).then((response : Show[]) => {this.shows = response;this.loading = false;});};constructor(private $location : ng.ILocationService,private $routeParams: any,private ShowService: ShowService) {PageValues.instance.title = "SEARCH";PageValues.instance.description = "Search for your favorite TV shows.";this.query = '';this.shows = [];this.loading = false;if (typeof $routeParams.query != "undefined") {this.performSearch($routeParams.query);this.query = decodeURI($routeParams.query);}}
}'use strict';
angular.module('app.core').controller('SearchController', SearchController);
使tsconfig.json更严格
此时,当我们在应用程序中获得typescript时,我们可以使我们的tsconfig.json更严格。这样,我们可以应用更多级别的代码正确性检查。
让我们来看看我们可以添加的一些有用的选项:
{ "compilerOptions": {"allowJs": true,"alwaysStrict": true, "module": "none","noImplicitAny": true,"noImplicitThis": true,"strictNullChecks": true,"strictFunctionTypes": true,"target": "es5","types": ["angular"]},"include": ["./src/**/*.ts"]
}
离开angular.js边界
值得一提的另一件事是使用typescript允许我们在不依赖angular.js结构的情况下构建应用程序的逻辑。如果我们需要构建一些业务逻辑,否则将受到angular.js约束的限制,这可能很有用,也就是说,我们希望采用动态多态,但是构建在angular.js依赖注入中,而不是限制而不是授权我们。
对于我们的玩具示例,让我们回到值提供者,这很简单但又可以为您提供一些关于如何不受限于angular.js结构的整体印象。
class PageValues {title : stringdescription : stringloading : booleanstatic instance : PageValues = new PageValues();
}
注意我们现在如何使用单例模式与静态实例,并摆脱angular.js模块连线。
现在我们可以通过以下方式从angular.js应用程序的任何部分调用它:
PageValues.instance.title = "VIEW";
PageValues.instance.description = `Overview, seasons & info for '${show.original_name}'.`;
结论
前端社区被认为是变化最快的社区。这可能会导致应用程序的客户端不断用顶级的自定义框架重写,以便开发人员团队仍然可以享受获得前端社区支持的好处。然而,并非每个开发团队,特别是大型企业,由于需要追逐业务目标而能够负担得起这样的奢侈品。
我的文章应该为这些团队提供一些帮助,以便连接到一些现代社区解决方案,而不会在很大程度上牺牲他们的业务目标。
我文章的最新部分显示的另一个值得注意的事情是,如果您想为前端应用程序架构添加一些灵活性,那么您可以轻松地摆脱框架的观点。
原文地址:https://www.codeproject.com/Articles/1272739/Cooking-angular-js-with-Typescript
用Typescript如火如荼地进行angular.js相关推荐
- angular js创建表单_如何优雅的使用 Angular 表单验证
随便说说,这一节可以跳过 去年参加 ngChine 2018 杭州开发者大会的时候记得有人问我: Worktile 是什么时候开始使用 Angular 的,我说是今年(2018年) 3 月份开始在新模 ...
- Angular.js示例应用程序
目录 介绍 演示应用程序概述 发布者端 网站端 Angular.Js简介 应用程序 服务 模块 依赖注入 路由 视图 控制器 作用域 指令 发布者 Angular.js网站 Require.js用法 ...
- angular js 使用pdf.js_胶水(框架) Stencil.js
去年的同一时间,我写了那篇<前端下半场:构建跨框架的 UI 库>推荐了 Stencil.js,当时是在项目的试验期.而 Stencil.js 已经在今年(2019 )的 6 月份,推出了 ...
- [Angular JS教程] HeroService: getHeroes failed: undefined 问题解决方法
最近在学习入门Angular JS,学习资源是https://angular.cn/tutorial, 在学习到 "https://angular.cn/tutorial/toh-pt6模拟 ...
- angular.js 嵌套路由
介绍 AngularJS 嵌套路由:,来看看嵌套的ui-router状态是怎么回事. ui-router和同属AngularJS框架一部分的ng-route一样强大. ui-router提供了让我们可 ...
- 如何使用多个参数调用Angular.js过滤器?
本文翻译自:How do I call an Angular.js filter with multiple arguments? As from the documentation , we can ...
- 如何在Angular.js选择框中使用默认选项
本文翻译自:How to have a default option in Angular.js select box I have searched Google and can't find an ...
- angular.js phonecat翻译
AngularJS 手机目录应用教程 概述 这个应用将带领开发者贯穿使用angularjs来开发一个web-app程序.这个应用程序是基于 Google Phone Gallery 但它现在已经不存在 ...
- Angular js 具体应用(一)
1,首先引用Angular 百度静态资源库搜索Angular 复制链接,在HTML中嵌入script 最好写在正文下面 <script type="text/javascript& ...
最新文章
- Windows核心编程 第四章 进程(下)
- javaScript call 函数的用法说明
- 方立勋_30天掌握JavaWeb_(JSP+JavaBean实现)简单计算器
- 描述一下Spring Bean 的生命周期
- 《spring-boot学习》-06-thymeleaf详解
- iF.SVNAdmin
- Android数据存储(1):SharedPreferences
- java如何获取scanner_java – 使用Scanner获取用户输入
- 计算机无法识别psp usb设备,PSP降级导致USB连接电脑识别问题解决办法
- LaTeX函数、符号及特殊字符
- 5V升压8.4V,5V转8.4芯片电路图
- 如何快速比对两个文件夹中的文件
- 分布式服务架构-第三章 服务化系统容量评估和性能保障
- 云原生、工业互联网之浅见
- 【JavaSE】Lambda表达式、接口组成更新、方法引用
- 系统设计基础 负载均衡
- 各版本VOS服务的停止、启动和重启命令详解
- 洗牌、发牌算法 (打乱扑克牌顺序)
- Web APIs第01天笔记——Web API介绍
- 针对尚硅谷教学微服务硅谷课堂在线学习平台的部分功能的自我改进
热门文章
- 子类重写方法aop切不到_SpringBoot源码之旅——AOP
- 呼叫 :邓伦粉丝!手机桌面壁纸来喽
- 承包你所有壁纸需求,高图网图片,美到窒息
- 质量超高的UI素材站!推荐UI\UX设计师
- C++static类静态成员函数及变量解析
- DLL注入(CreateRemoteThread方式)
- 使用DPDK打开Open vSwitch(OvS) *概述
- VPP /什么是VPP?读这篇文章就够了
- Turbo码:3GPP TS 36.212
- python读取文件最后几行_python读取文件最后一行两种方法