第1章 课程介绍
课程链接:
https://coding.imooc.com/class/449.html
课程文档:
Typescript推荐文档:
https://itdashu.com/docs/typescriptlesson.html
https://www.wenjiangs.com/docs/typescript-introduction-2
第2章 你好 Typescript: 进入类型的世界
开始
除了课程中的内容,结合自己的一些了解对齐做了补充。另外这里推荐一个也还不错的Typescript学习的教程(和慕课的课程做了下比较,这里更为详尽), 即第一章的Typescript推荐文档。
为什么要使用Typescript?
静态类型
回答这个问题前,先来看看下面这些 JavaScript 中的常见错误:
- Uncaught TypeError: Cannot read property
- TypeError: ‘undefined’ is not an object
- TypeError: null is not an object
- TypeError: Object doesn’t support property
- TypeError: ‘undefined’ is not a function
- TypeError: Cannot read property ‘length’
仔细看下不难发现,这些错误大都是一些比较初级的类型错误。
JavaScript 只会在 运行时
才去做数据类型检查,而 TypeScript 作为静态类型语言,其数据类型是在 编译期间
确定的,编写代码的时候要明确变量的数据类型。使用 TypeScript 后,这些低级错误将不再发生。
越来越多前端框架和第三方库对TS的支持
我们学习一门新技术会关心它的生命力问题,如果这门技术在较短时间内就要被淘汰,那花费大量的时间学习也是不划算的。TypeScript 能够保持长久生命力的另一个原因,就是统治前端的三大框架对 TypeScript 的支持。
- Angular 是 TypeScript 最早的支持者,Angular 官方推荐使用 TypeScript 来创建应用。
- React 虽然经常与 Flow 一起使用,但是对 TypeScript 的支持也很友好。
- Vue3.0 正式版即将发布,由 TypeScript 编写。
从国内的氛围来看,由前端三大框架引领的 TypeScript 热潮已经涌来,很多招聘要求上也都有了 TypeScript 的身影。
越来越多耳熟能详的大项目都使用了typescript,如Vue3.0, Angular, Ant-design, nextJs等。State of JS权威调查报告显示,2019年58%的开发者正在使用并愿意继续使用Typescript。
兼容 JavaScript 的灵活性
TypeScript 虽然严谨,但没有丧失 JavaScript 的灵活性,TypeScript 非常包容:
- TypeScript 通过
tsconfig.json
来配置对类型的检查严格程度。 - 可以把
.js
文件直接重命名为.ts
。 - 可以通过将类型定义为
any
来实现兼容任意类型。 - 即使 TypeScript 编译错误,也可以生成 JavaScript 文件。
TS的当然也是缺点的,如增加了一些学习成本,短期内增加了开发成本等。所以在项目中可以根据情况是否使用Typescript。对于中大型项目来说,使用Typescript长期收益是更为明显的,但是对于小型项目或者不需要维护的项目,就没有必要增加开发的时间了。
编程语言类型
动态类型语言(Dynamically Typed Language): 运行期间才会进行类型检查的语言,代表JS,PHP, Python, C#等。这种语言只有在运行的时候才会发现错误。
静态类型语言(Statically Typed Language):编译期间进行类型检测的语言,代表TS, Java,C, C++等。
安装 Typescript
Typescript 官网地址: https://www.typescriptlang.org/zh/
使用 nvm 来管理 node 版本: https://github.com/nvm-sh/nvm
安装 Typescript:
1 | npm install -g typescript |
使用 tsc 全局命令:
1 | # 查看 tsc 版本 |
安装Typescript调试工具
1 | npm install -g ts-node |
使用 ts-node 全局命令:
1 | # 查看 ts-node 版本 |
原始数据类型
Typescript 文档地址:Basic Types
Javascript 类型分类:
原始数据类型 (primitive values):
- Boolean
- Null
- Undefined
- Number
- BigInt
- String
- Symbol
1 | let isDone: boolean = false |
1 | let notSure: any = 4 |
Array 和 Tuple
Typescript 文档地址:Array 和 Tuple
1 | //最简单的方法是使用「类型 + 方括号」来表示数组: |
interface 接口
Typescript 文档地址:Interface
Duck Typing(interface 接口称号) 概念:
如果某个东西长得像鸭子,像鸭子一样游泳,像鸭子一样嘎嘎叫,那它就可以被看成是一只鸭子。
1 | // 我们定义了一个接口 Person |
函数
Typescript 文档地址:Functions
1 | // 来到我们的第一个例子,约定输入,约定输出 |
类型推论,联合类型 和 类型断言
Typescript 文档地址:类型推论 - type inference
1 | // 我们只需要用中竖线来分割两个 |
1 | // 这里我们可以用 as 关键字,告诉typescript 编译器,你没法判断我的代码,但是我本人很清楚,这里我就把它看作是一个 string,你可以给他用 string 的方法。 |
1 | // typescript 在不同的条件分支里面,智能的缩小了范围,这样我们代码出错的几率就大大的降低了。 |
Class 类
面向对象编程(OOP)的三大特点
- 封装(Encapsulation):将对数据的操作细节隐藏起来,只暴露对外的接口。外界调用端不需要(也不可能)知道细节,就能通过对外提供的接口来访问该对象,
- 继承(Inheritance):子类继承父类,子类除了拥有父类的所有特性外,还有一些更具体的特性。
- 多态(Polymorphism):由继承而产生了相关的不同的类,对同一个方法可以有不同的响应。
1 | class Animal { |
- public 修饰的属性或方法是公有的,可以在任何地方被访问到,默认所有的属性和方法都是 public 的
- private 修饰的属性或方法是私有的,不能在声明它的类的外部访问
- protected 修饰的属性或方法是受保护的,它和 private 类似,区别是它在子类中也是允许被访问的
类与接口
1 | interface Radio { |
枚举 Enums
1 | // 数字枚举,一个数字枚举可以用 enum 这个关键词来定义,我们定义一系列的方向,然后这里面的值,枚举成员会被赋值为从 0 开始递增的数字, |
泛型 Generics(重难点)
泛型(Generics)是指在定义函数、接口或类的时候,不预先指定具体的类型,而在使用的时候再指定类型的一种特性。
1 | function echo(arg) { |
泛型第二部分 - 泛型约束
在函数内部使用泛型变量的时候,由于事先不知道它是哪种类型,所以不能随意的操作它的属性或方法
1 | function echoWithArr<T>(arg: T): T { |
泛型第三部分 - 泛型与类和接口
1 | class Queue { |
类型别名 和 交叉类型
类型别名,就是给类型起一个别名,让它可以更方便的被重用。
1 | let sum: (x: number, y: number) => number |
1 | interface IName { |
声明文件
1 | // 通常写在定义文件里面(如:jQuery.d.ts),仅仅用于编译检查,并没有实现,要通过script标签引入jQuery才行。 |
内置类型
1 | // global objects |
Typescript 还提供了一些功能性,帮助性的类型,这些类型,大家在 js 的世界是看不到的,这些类型叫做 utility types,提供一些简洁明快而且非常方便的功能。
1 | // partial,它可以把传入的类型都变成可选 |
第3章 初识 Vue3.0: 新特性详解
开始
Vue3 的文档地址: https://v3.cn.vuejs.org/
Vue3:两年开发,99位贡献者,2600次提交,628次Pull Request
Vue3 支持 2 的大多数特性
性能提升
- 打包大小减少 41%
- 初次渲染快 55%,更新快 133%
- 内存使用减少 54%
Composition API (组合API)
- ref 和 reactive
- computed 和 watch
- 新的生命周期函数
- 自定义函数 - Hook 函数
其他新增特性
- Teleport - 瞬移组件的位置
- Suspense - 异步加载组件的新福音
- 全局API的修改和优化
- 更多的试验性特性
更好的 Typescript 支持
为什么要有 Vue3.0?
- Vue2 中,随着功能的增长,复杂组件的代码维护变得难以维护。(由于Vue2组件变量方法都在一个对象里面,逻辑多的时候不方便查找相关的方法或属性,在Vue2用通常用mixin来解决,但是mixin虽然把相同的逻辑放到一起了,但是又命名冲突和不方便复用问题)
- Vue2 对于 Typescript 的支持非常的有限
配置 vue3 开发环境
1 | // 安装或者升级 |
然后的步骤
- Please pick a preset - 选择 Manually select features
- Check the features needed for your project - 多选择上 TypeScript,特别注意点空格是选择,点回车是下一步
- Choose a version of Vue.js that you want to start the project with - 选择 3.x (Preview)
- Use class-style component syntax - 输入 n,回车
- Use Babel alongside TypeScript - 输入n,回车
- Pick a linter / formatter config - 直接回车
- Pick additional lint features - 直接回车
- Where do you prefer placing config for Babel, ESLint, etc.? - 直接回车
- Save this as a preset for future projects? - 输入n,回车
启动图形化界面创建
1 | vue ui |
遇到问题:
这里我启动会报错: ERROR Error: Cannot find module 'vue-loader-v16/package.json'
, 根据网上的教程安装 npm i -D vue-loader-v16
并且升级npm后还是报错,变成了 ERROR Error: Cannot find module 'fork-ts-checker-webpack-plugin-v5'
解决方法:重新创建项目(导致原因不清楚,这里我重新创建项目就好了,现在想想可能是npm更新后应该要重新开启一个cmd来让npm最新版本生效。另外,npm经常会遇到这种依赖的问题,如果不是开发自己的插件的话,我觉得用yarn来管理包会好点)
项目结构和插件
推荐给大家安装的插件
如果 eslint 不生效,可以在根目录创建 .vscode 文件夹,然后在文件夹中创建 settings.json 然后输入
1 | { |
Ref 语法
setup 有个语法糖写法,vue会自动收集其里面的依赖。如下面代码 template 中就可以直接使用 name、age、change 了
1 | <script lang="ts" setup> |
1 | <template> |
Reactive 函数
1 | import { ref, computed, reactive, toRefs } from 'vue' |
使用 ref 还是 reactive 可以选择这样的准则
- 第一,就像刚才的原生 javascript 的代码一样,像你平常写普通的 js 代码选择原始类型和对象类型一样来选择是使用 ref 还是 reactive。
- 第二,所有场景都使用 reactive,但是要记得使用 toRefs 保证 reactive 对象属性保持响应性。
虽然 ref 也可以实现对象的响应式,但是使用的时候都要 .value 容易导致太多 .value,所以对象还是推荐用 reactive 吧
Vue3 生命周期
生命周期基本没有变化,给 beforeDestroy 和 destroyed 两个生命周期起了别名为 beforeUnmount 和 unmounted。主要就关注下Composition API中生命周期钩子的使用,如下:
在 setup 中使用的 hook 名称和原来生命周期的对应关系:
选项式 API | Hook inside setup |
---|---|
beforeCreate |
Not needed* |
created |
Not needed* |
beforeMount |
onBeforeMount |
mounted |
onMounted |
beforeUpdate |
onBeforeUpdate |
updated |
onUpdated |
beforeUnmount |
onBeforeUnmount |
unmounted |
onUnmounted |
errorCaptured |
onErrorCaptured |
renderTracked |
onRenderTracked |
renderTriggered |
onRenderTriggered |
activated |
onActivated |
deactivated |
onDeactivated |
详细用法见:https://vue3js.cn/docs/zh/api/options-lifecycle-hooks.html#beforecreate
1 | import { onMounted, onUpdated, onRenderTriggered } from ‘vue’ |
侦测变化 - watch
1 | // watch 简单应用(data是一个ref对象,setup中的普通变量不能改变所以不需要监控?) |
模块化开发 第一部分 鼠标追踪器
1 | // 在单组件内添加对应逻辑 |
vue3 这种实现方式的优点
- 第一:它可以清楚的知道 xy 这两个值的来源,这两个参数是干什么的,他们来自 useMouseTracker 的返回,那么它们就是用来追踪鼠标位置的值。
- 第二:我们可以xy 可以设置任何别名,这样就避免了命名冲突的风险。
- 第三:这段逻辑可以脱离组件存在,因为它本来就和组件的实现没有任何关系,我们不需要添加任何组件实现相应的功能。只有逻辑代码在里面,不需要模版。
模块化难度上升 - useURLLoader
1 | // 安装 axios 注意它是自带 type 文件的,所以我们不需要给它另外安装 typescript 的定义文件 |
1 | // 使用 urlLoader 展示狗狗图片(注意,这里没有使用await什么的) |
模块化结合typescript - 泛型改造
1 | // 为函数添加泛型 |
使用 defineComponent 包裹组件
使用该函数可以方便定义组件,使得组件定义时有相应的语法提示。
1
2
3
4
5
6
7
8
9
10
11 // 下面是一个vue3中组件的定义,普通的对象IDE无法智能提示,试着用 defineComponent() 编写下。
// import { defineComponent } from 'vue'
// const component = defineComponent({})
const component = {
name: 'HelloWorld',
props: { msg: 'this is a word!' },
setup(props, context){
// props:组件接收的props
// context:组件的上下文对象,相当于vue2的this,但是只实现了三个方法(attrs, slots, emit)
}
}
Teleport - 1
Teleport 瞬间移动
在日常使用中,我们会遇到子组件使用到弹窗(Dialog), 这是弹窗是在子组件中的,那么使得Dialog容易受到组件的样式污染,同时在DOM结构上,Dialog也应该出现在最顶层的结点上,不干扰子组件的DOM结构。如此就可以用到Teleport了,它就类似一个传送门,把Modal组件渲染到顶层的另外一个DOM结点中。
1 | <template> |
Teleport - 2
Modal 组件完善(打开、关闭)
1 | <template> |
在 App 组件中使用
1 | const modalIsOpen = ref(false) |
Suspense - 1
异步请求好帮手第一部分
- 解决异步请求的困境
- Suspense 是 Vue3 推出的一个内置的特殊组件
- 如果使用 Suspense, 要返回一个 promise
定义一个异步组件,在 setup 返回一个 Promise,AsyncShow.vue
1 | <template> |
在 App 中使用
1 | <!-- 省略了script里面的导入,这里async-show即是异步组件 --> |
Suspense - 2
异步请求好帮手第二部分
使用 async await 改造一下异步请求, 新建一个 DogShow.vue 组件
1 | <template> |
Suspense 中可以添加多个异步组件
1 | <Suspense> |
全局 API 修改
Vue2 的全局配置
1 | import Vue from 'vue' |
Vue2 这样写在一定程度上修改了 Vue 对象的全局状态。
- 第一,在单元测试中,全局配置非常容易污染全局环境,用户需要在每次 case 之间,保存和恢复配置。有一些 api (vue use vue mixin)甚至没有方法恢复配置,这就让一些插件的测试非常的困难。
- 第二,在不同的 APP 中,如果想共享一份有不同配置的 vue 对象,也变得非常困难。
Vue3 的修改
1 | import { createApp } from 'vue' |
全局API修改:
全局配置:Vue.config -> app.config
- config.productionTip被删除
- config.ignoredElements改名为 config.isCustomElement
- config.keyCodes 被删除
全局注册类API
- Vue.component -> app.component
- Vue.directive -> app.directive
行为扩展类API
- Vue.mixin -> app.mixin
- Vue.use -> app.use
Global API Treeshaking
1 | // vue2 |
第4章 项目记录
Vue3没有提供项目结构参考。这里采用结构如下:
1 | /assets |
自建样式库
CSS样式库有Bootstrap、tailwindcss、Foundation
项目配置:
1 | // settings.json |
第5章 表单的世界 - 完成自定义 Form 组件
第6章 请你吃全家桶 - 初步使用 vue-router 和 vuex
第7章 前后端结合 - 项目整合后端接口
第8章 通行凭证 - 权限管理
第9章 道高一尺 - 上传组件
第10章 最终的功能 - 编辑和删除文章
第11章 持续优化
第12章 项目构建和部署
第13章 课程总结
本文链接: http://www.ionluo.cn/blog/posts/8d6494e5.html
版权声明: 本作品采用 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议 进行许可。转载请注明出处!