33 书写声明文件之砍柴:为不同类型库书写声明文件

5.3.1 模块插件或 UMD 插件 一些模块和插件是支持插件机制的,比如我们常见的 jQuery,它的插件有非常多。我们可以为库书写声明文件的同时,为库的插件定义声明文件,可以参考官方模板 module-plugin.d.ts。 5.3.2 全局插件 全局插件往往会修改全局中一些对象,在这些对象上添加或修改属性方法,比如下面的示例: // add-methods-to-string.js String.prototype.getFirstLetter = function() { return this[0]; }; 这段代码在 String 构造函数的原型对象上添加一个 getFirstLetter 方法,这个方法可以返回字符串的第一个字符。我们创建一个字符串,就可以调用这个方法。来讲下这个原理,我们在 String 构造函数原型对象上添加一个方法,这个方法就会被 String 创建的实例继承,如果我们使用new String(‘Lison’)的方式创建一个实例 name,那么这个 name 将是一个对象类型的值,它的属性是 0 开始到 n 的数字,属性值对应字符串的第 1 个、第 n 个字符;但是像例子中这样使用const name = 'Lison’字面量的形式定义的 name,其实是个字符串类型的值,字符串就不会继承构造函数的方法了,以为它不是对象,但事实是它可以调用getFirstLetter方法。这是因为它在调用方法的时候,会先将这个字符串包装成一个封装对象,在内部即使用 String 构造函数,所以它依然可以调用原型对象上的方法。 我们在 html 文件里引入这个 js 文件后创建一个字符串,这个字符串就可以调用 getFirstLetter 方法: <script type="text/javascript" src="./add-methods-to-string.js"></script> <script type="text/javascript"> var str = "Lison"; console.log(str.getFirstLetter()); // "L" </script> 如果我们在 TS 中使用,就需要为这个创建声明文件,我们创建一个声明文件 global-plugin.d.ts:...

March 13, 2024 · zlzong

34 搭建基础项目

这一章是实战章节,我们将会使用 Vue+TypeScript 来开发一个简单管理后台,这个实战项目的目的是演示如何在Vue 项目中使用 TypeScript 进行开发,而不是为了实现一个管理后台。所以我们在开发的时候,以尽可能多的展示如何使用 TypeScript 结合 Vue 全家桶进行开发为前提,进行这个实战项目的开发,对于涉及到相同知识点的功能性代码,我们会尽可能不去重复讲解。 6.1.1 安装Vue CLI 本小节我们先来进行第一步,就是创建我们的初始项目,首先你需要在全局安装 Vue 命令行工具 Vue CLI,首先你要确定你安装了 NodeJS,如何安装我们已经在1.3小节讲过了,我们直接看如何安装 Vue CLI: sudo npm install -g @vue/cli Windows系统直接运行npm install -g @vue/cli命令即可。 因为是在全局安装,所以你可能需要以管理员身份去运行,Mac中就是前面加sudo然后输入密码。安装之后你可以通过检查他的版本号来确定是否成功安装: vue -V 或者 vue --version 注意这里是使用vue命令,而不是@vue/cli,如果使用-V参数一定记着是大写的V,我这里安装的是3.3.0版本的,如果你发现你创建的项目和我创建的项目包含的文件或者配置信息有差异,有可能是版本差异造成的,你也可可以直接安装与我相同的版本。 6.1.2 使用Vue CLI创建项目 安装好Vue CLI后,在终端启动Vue的可视化项目管理页面,运行如下命令: vue ui 几秒钟之后就会自动打开浏览器在浏览器中打开一个本地页面,然后打开创建项目界面: 选择要存放新项目的文件夹后,点击底部的“在此创建新项目”,然后进入配置流程,一共四个流程:“详情” - “预设” - “功能” - “配置”,我们来逐个配置。 (1) 详情 填写项目名,这里我们写的是"vue-ts-project",然后选择包管理器,我这里选的是npm,如果你建了git仓库,你可以在git栏填写git的仓库地址。配置完成后点击“下一步”。 (2) 预设 每次创建一次项目,你的功能配置都可以保存为预设,方便下次直接使用,这里我们先选择手动,来手动配置项目。然后点击“下一步”。 (3) 功能 这里我们勾选这几项: Babel:使用Babel可以将新特性语法转为低版本浏览器支持的语法; TypeScript:这个肯定要勾选了,因为我们要使用TypeScript开发; Router:我们要开发单页面SPA应用,所以页面间的跳转需要使用前端路由; Vuex:多个页面直接或者组件之间的通信可以使用Vuex来做状态管理; CSS Pre-processors:CSS预处理器,如果你使用Less或者Sass等CSS预处理器编写CSS样式,则勾选这项; Linter/Formatter:代码规范或格式检查器,如果你需要使用TSLint对代码规范或格式进行检验,勾选这项; 使用配置文件:如果需要将一些插件的配置保存在各自的配置文件中,则需要勾选这项。 配置完成后点击“下一步”。...

March 13, 2024 · zlzong

35 封装接口请求

我们在开发中广泛使用的axios调用接口,为了更好地调用,做一些全局的拦截,我们通常会对其进行一下封装,本小节我们就来看下如何使用TypeScript对它进行封装,使其同时能够有很好的类型支持。 首先我们需要安装axios,如何安装依赖我们在1.3小节学习过了,这里直接安装: npm install axios 我们在src文件夹下创建utils文件夹,然后在utils文件夹创建*axios.ts文件,axios这个插件自带声明文件,所以我们不需要另外安装了。先来看下最基础的封装: import axios, { AxiosInstance, AxiosRequestConfig, AxiosPromise,AxiosResponse } from 'axios'; // 引入axios和定义在node_modules/axios/index.ts文件里的类型声明 class HttpRequest { // 定义一个接口请求类,用于创建一个axios请求实例 constructor(public baseUrl: string) { // 这个类接收一个字符串参数,是接口请求的基本路径 this.baseUrl = baseUrl; } public request(options: AxiosRequestConfig): AxiosPromise { // 我们实际调用接口的时候调用实例的这个方法,他返回一个AxiosPromise const instance: AxiosInstance = axios.create() // 这里使用axios.create方法创建一个axios实例,他是一个函数,同时这个函数包含多个属性,就像我们前面讲的计数器的例子 options = this.mergeConfig(options) // 合并基础路径和每个接口单独传入的配置,比如url、参数等 this.interceptors(instance, options.url) // 调用interceptors方法使拦截器生效 return instance(options) // 最后返回AxiosPromise } private interceptors(instance: AxiosInstance, url?: string) { // 定义这个函数用于添加全局请求和响应拦截逻辑 // 在这里添加请求和响应拦截 } private mergeConfig(options: AxiosRequestConfig): AxiosRequestConfig { // 这个方法用于合并基础路径配置和接口单独配置 return Object....

March 13, 2024 · zlzong

36 实现登录页并用Mock响应请求

本小节我们来开发一个登录页,调用api请求,然后使用mockjs模拟请求响应,来返回登录成功与否的状态。登录成功之后,我们会跳到后台系统首页。如果没有登录,无论访问后台系统哪个页面的url,都会跳到登录页。接下来我们开始学习。 首先添加一个登录页,在src/views文件夹下创建一个login文件夹,所有和login页相关的文件都放到这个文件夹内,然后在这个文件夹创建一个index.tsx文件。因为项目默认添加的两个页面About.vue和Home.vue都是使用Vue单文件.vue后缀的形式,所以我们添加一个以.tsx为后缀的文件,来学习如何使用tsx写法写vue。 // src/views/login/index.tsx import { Component, Vue } from 'vue-property-decorator' @Component export default class LoginPage extends Vue { protected render() { return ( <div>login</div> ) } } 我们这里用到一个新的依赖"vue-property-decorator",你需要先安装它,然后在这里引入,我们这里暂时只用到Component和Vue,Component是一个装饰器工厂函数,可以用来修饰我们要作为组件实例的类的定义。它可以传入一个对象参数,用来配置组件的一些信息,也可以不传参数,我们待会儿会补充一些参数,现在我们先使用默认参数。 使用Component装饰器修饰之后,这个类LoginPage的定义再继承Vue,它的定义就包含了一些组件需要的属性等,然后我们这里就可以定义一个render方法,用来书写渲染的dom内容。这个方法名是固定的,Vue会拿到这个方法返回的内容去渲染实际的DOM。 注意它的写法,return返回的内容用括号包住,然后里面就像写html一样写html标签,还可以写组件,当然JSX语法内容不是简答几句话可以概括完的,我们一点一点来看。这里我们就只渲染一个div标签,然后里面包含字符串"login"。 这里还有一点要特别注意,一个组件最外层只能由一个节点包裹,也就是这里你要将所有内容都包在这个<div>标签里,不能有和这个<div>标签同级的第二个标签了。 接下来这个组件就可以用了,我们定义一下路由,使得我们可以把这个组件作为一个页面访问。在src/router/routes.ts文件的路由配置里,增加一个: // ... export default [ // ... { path: '/login', name: 'login', component: () => import('@/views/login/index'), }, ] 现在你可以在浏览器里访问login页面啦,默认情况下本地起的服务路径为http://localhost:8080/#/login,如果你起了别的服务,可能端口号8080会是别的,你可以直接在控制台查看服务的url。打开这个url之后,你会看到页面上有login这个词,说明你前面的这些步骤没有疏漏,如果出现问题,需要你仔细对照一下上面讲解的步骤啦。 接下来我们要添加两个输入框,一个用来输入用户名,一个用来输入密码。再添加一个按钮,用来请求登录api,我们对前面render方法做一些补充: // src/views/login/index.tsx // ... @Component export default class LoginPage extends Vue { public user_name: string = '' public password: string|number = '' protected render() { return ( <div class='login-page'> <input v-model={ this....

March 13, 2024 · zlzong

37 搭建后台界面布局和结合Vuex实现完整登录流程

本小节我们来搭建一个后台基本框架,所有的页面除了登录页,都在这个框架里展示,左侧显示菜单,右侧显示页面,我们先看下要实现的效果: 接下来我们继续上个小节的节奏进行。在开始之前我们需要安装一个UI组件库,Ant Design Vue,它是React版本的Ant Design组件库的Vue版本,因为Ant Design是使用TypeScript编写的,类型声明文件较为完善,而Ant Design Vue延用这些声明文件,所以可以更好地在TypeScript环境下使用。首先来安装它:npm install ant-design-vue。 接下来我们在入口文件引入组件库及其样式,并且全局注册它: // src/main.ts // ... import AntVue from 'ant-design-vue' import 'ant-design-vue/dist/antd.css'; Vue.use(AntVue) // ... 顺便修改一下src/App.vue的样式,我们在App.vue文件的样式里,增加如下样式,使页面具有高度: html,body{ height: 100%; margin: 0; padding: 0; } #app{ height: 100%; .home{ text-align: center; } } 接下来我们在src/components文件夹下创建一个TMain文件夹,之所以叫这个,是因为根据Vue开发规范强烈建议组件名使用大写字母开头,然后使用驼峰形式命名,而且不要使用单个单词,应该统一加个前缀,所以我们这个框架组件叫做TMain,然后在TMain文件夹下创建一个index.vue文件。我们来使用单文件的形式编写组件。我们先只添加基本的代码: <template> <div class="t-main-wrap"> <!-- 布局容器组件 --> <a-layout style="height: 100%"> <!-- 左侧容器组件 --> <a-layout-sider></a-layout-sider> <a-layout> <!-- 顶部容器组件 --> <a-layout-header style="background: #fff"></a-layout-header> <!-- 内容容器组件 --> <a-layout-content> <!-- 路由视图渲染组件 --> <router-view></router-view> </a-layout-content> </a-layout> </a-layout> </div> </template> <script lang="ts"> import { Component, Vue } from 'vue-property-decorator' @Component({ name: 'TMain' }) export default class TMain extends Vue {} </script> <style lang="less"> ....

March 13, 2024 · zlzong

38 使用TypeScript开发Vue组件和使用Vue组件

本小节我们将学习使用Vue+TypeScript进行组件的开发和使用。我们在本章前面的小节中,虽然讲了很多内容,但是还没有封装一个可以复用的组件,没有涉及到属性和自定义事件。本小节我们将通过封装一个CountTo组件,展示如何封装一个组件。 首先我们先将创建项目时初始添加的src/views/Home.vue文件改为如下简单结构,把没用的先删掉: <template> <div class="home"> </div> </template> <script lang="ts"> import { Component, Vue } from 'vue-property-decorator' @Component({ name: 'HomePage' }) export default class Home extends Vue {} </script> 然后我们来封装CountTo组件,这里需要安装一个第三方插件:npm install countup,这个插件可以实现一个数字的动画过渡效果,它虽然有声明文件,但是有问题,所以我们自己写一份声明文件,使用我们自己定义的声明文件。 首先在根目录下创建一个types文件夹,然后在types文件夹下创建一个countup文件夹,也就是和我们要引入的模块同名的文件夹,然后在这个文件夹下创建一个index.d.ts声明文件。创建好之后,我们要用这个声明文件覆盖node_modules/countup里的声明文件,注意,不是去修改node_modules/countup/index.d.ts文件的内容,而是通过配置tsconfig.json里的paths字段来指定countup模块的声明文件位置,配置如下: { "comilerOptions": { "paths": { "countup": [ "./types/countup/index.d.ts" ], } } } 这样,当我们使用import去引入countup插件的时候,编译器就会去我们这里指定的路径加载声明文件。接下来我们修改下声明文件,内容如下: // types/countup/index.d.ts declare function CountUp(target: string, startVal: number, endVal: number, decimals: number, duration: number, options: any): void; declare module CountUp { var options: CountUpOptions; function version(): string; function printValue(value: any): void; function count(timestamp: any): void; function start(callback: Function): boolean; function pauseResume(): void; function reset(): void; function update(newEndVal: number): void; } interface CountUp { new(target: string, startVal: number, endVal: number, decimals: number, duration: number, options: any): CountUp; options: CountUpOptions; version(): string; printValue(value: any): void; count(timestamp: any): void; start(callback?...

March 13, 2024 · zlzong

39 结束语

TypeScript 的基础知识,以及使用 TypeScript 开发 Vue 应用的实战内容,我们到这里就已经学习完了。相信你对 TypeScript 已经有了一个系统、全面的了解了。最后,Lison 最后再跟你絮叨几句。 7.1.1 使用TypeScript心得 如果你过去使用 React 开发 web 应用,在不使用 TypeScript 的情况下,编辑器对代码的提示并不是很好,但是如果使用 TypeScript,因为在编写代码阶段,数据的结构都是很明确的,所以编辑器会进行很友好的代码提示。这样我们在使用一些自己封装的方法,或者第三方对 TypeScript 支持良好的一些插件的时候,能减少很多去翻文档翻 api 介绍的时间。使用 TypeScript 使得代码的可读性大大,比如对于一些数值类型的常量,我们可以使用枚举值定义,这样就可以只用枚举成员代替数值字面量,提高可读性。对于函数的定义,在定义函数的时候定义完整的函数类型,包括参数类型和返回值类型等,在调用的时候,通过编辑器的代码提示,就可以看到需要几个参数,每个参数有什么要求;对函数的返回值进行操作的时候,能够知道操作的是什么类型值,可以做哪些操作。 如果你使用 Vue 开发 web 应用,也是可以使用 TypeScript 的,只不过,vue 是通过补充声明文件的方式,弥补了类型声明,但是并不是很完善,所以我们只能期待 Vue3.0 的到来了。但是如果使用TypeScript 开发 Vue 应用,要获得更好的类型支持,要在 script 里,通过类形式定义组件,这样编译器可以尽可能地推断一些类型。虽然 Vue2.x 对 TypeScript 的支持并不很好,但是如果你使用VSCode 进行开发,即使是不使用 TypeScript,也能得到一些代码提示。 如果你对 TypeScript 掌握的差不多了,想练手的话,可以自己先创建一个小项目来练练手。如果是实际项目开发,小型的个人完成的项目并不推荐使用 TypeScript,因为项目不复杂,内容不是很多的情况下,使用 TypeScript 会增加你的工作量,但带来的收益又不是很大。但如果是大型的多人协作的项目,或者是需要多处复用的开源或内部使用的插件库,极力推荐使用 TypeScript 进行开发,因为他可以帮助你提高代码质量,方便使用者快速上手,减少翻阅文档的次数,再配合单元测试,可以说这套代码就非常可靠了。 7.1.2 TypeScript前景 过去,在 ES6 标准颁布之前,社区有众多语法糖工具,比如当初的 CoffeeScript,可以说还是受到很多人追捧的。但是 ES6 标准公布之后,随着 Babel 等工具对 ES6 标准的支持,再加上 ES6 前卫的语法标准,大家不再需要 CoffeeScript,使用 Babel 即可将 ES6 代码转义为兼容新旧浏览器的代码。...

March 13, 2024 · zlzong