简介
- js
- 优点:不容易报错
- 缺点:
- ES6前使用面向对象比较麻烦(需要结合原型+构造函数);
- 没有变量类型,会根据值来定义数据类型;js的变量是动态类型--可能会导致后面做运算时因为值发生改变,数据类型不匹配可能导致不会报错,只有当程序执行到才会报错。
- js定义函数时参数没有类型的限制,我们可以在调用函数时传任意数据类型,这样就导致在执行某个语句后程序才出现报错的情况
- ts
- 是微软开发的,为了解决js所带来的缺点,但不是为了替代js(因为js对于前端的影响非常大)
- 引入了数据类型,让js从动态语言转成静态语言。即变量声明时可以指定类型,类型一旦执行不能发生变化,否则会提示报错(但还是可以编译,后期我们可以通过webpack配置解决)。
- 目前情况下,ts文件不能直接被JS解析器直接执行。即ts文件不能在浏览器上直接执行
- ts可以通过配置让js变得严谨或者松散
- ts中可以使用js中所有的语法
typescript编译
默认情况下.ts
文件是不能直接在浏览器使用的,需要通过node
中的typescript
进行编译生成js。
步骤:
- 下载并安装
Node.js
- 使用npm全局安装
typescript
npm i -g typescript
- 创建
hello.ts
文件,并编写代码
let a:string = "hello typescript"
- 使用
tsc
命令进行编译
tsc hello.tsc
基本类型
类型有:number、string、boolean、字面量、any、unknown、void、never、object、array、tuple、enum
用法:
let a:number = 20
字面量
let n1:10
n1 = 10
# n1 = 20 报错
unknown类型和any类型
- 可以将任意类型的值赋值给unknown类型或any类型的变量;
- 可以将any类型的变量赋值可以任意类型的变量;但是不能将unknown类型的变量赋值给任意类型(any类型除外)的变量
- 简单理解为any会导致原本变量定义的数据类型不起作用了;或者理解为any权力最大,可以做任何的赋值操作。所以如果一个类型不确定时推荐使用unknown
let n1:unknown
let n2
n1 = 10
n1 = "hello"
n2 = 20
n2 = "ts"
let n3:string = "ok"
n3 = n2
# n3 = n1 这里会报错
类型断言
有些情况下,变量的类型对于我们来说是很明确,但是TS编译器却并不清楚,此时,可以通过类型断言来告诉编译器变量的类型,一般用在变量设置为unknown
类型时
let n1:unknown
let s = "hello"
n1 = "ts"
# s = n1 报错
# 方式1: 变量 as 类型
s = n1 as string;
# 方式2: <类型>变量
s = <string>n1
对象
let o :{name:string} = {name:'zs'}
# 下面会报错
# let o: { name: string } = { name: 'zs', age: 20 }
# 属性设置多个;propName是变量别名,可以随意起
let o1:{name:string,[propName:string]:any} = {name:'ls',age:18}
函数
let sum: (n1: number, n2: number) => number
sum = function (n1, n2) {
return n1 + n2
}
数组
let arr1: string[];
arr1 = ['i','love','ts']
let arr2: Array<number>;
arr2 = [10,20,30]
元组
固定长度的数组
let t1: [string,number]
t1 = ['ok',200]
枚举
enum Gender{
Male,
Female
}
let o:{name:string,gender:Gender}
o = {name:'莉莉',gender:Gender.Female}
其他
或者
# n1的值可以是10或者string
let n1: 10 | string
n1 = 'hello'
n1 = 10
并且
let j: { name: string } & { age: number };
j = {name: '孙悟空', age: 18};
编译选项
自动编译单个文件
使用 -w 指令后,TS编译器会自动监视文件的变化,并在文件发生变化时对文件进行重新编译。【-w,表示watch】
tsc -w hello.ts
自动编译整个文件夹
tsconfig.json是ts编译器的配置文件,ts编译器可以根据它的信息来对代码进行编译
- 在项目根目录下创建空的
tsconfig.json
文件 - 然后执行
tsc -w
命令会实时监控当前目录以及子目录下的所有文件的变化,对.ts
后缀的文件进行自动编译
编译子选项
include
- 默认情况下当前目录以及子目录下的所有文件都会进行编译,如果要对某几个目录下的文件进行编译的话,则需要指定此选项。
- 默认值为:
["**/*"]
// 对src、test目录下的所有文件以及所有子文件都进行编译
"include": ["src/**/*","test/**/*"]
exclude
- 定义不需要进行编译的目录
"exclude":["node_modules"]
extends
- 定义多个配置文件,当配置文件需要按结构进行分离时可采取此方式
// 会自动包含config目录下的basic.json文件
"extends": "./config/basic"
files
- 指定被编译的文件列表
"files":["1.ts","2.ts","3.ts"]
compilerOptions
重点
- 此选项包含多个子选项,用来完成对编译的配置
target
- 设置ts代码编译的目标版本
- 可选值:ES3(默认)、ES5、ES6/ES2015、ES7/ES2016、ES2017、ES2018、ES2019、ES2020、ESNext
"compilerOptions":{
"target":"ES6"
}
outDir
- 默认情况下,编译后的js文件会和ts文件位于相同的目录,设置outDir后可以改变编译后文件的位置
"compilerOptions": {
"outDir": "dist"
}
outFile
- 默认情况下一个ts文件对应编译成一个js文件,如果需要打包成一个js文件的话则可以设置此选项
"compilerOptions":{
"outFile":"dist/bundle.js"
}
allowJs
- 默认情况下不对js文件进行编译,如果需要进行编译的话则可以设置此选项
"compilerOptions":{
"allowJs": true
}
removeComments
- 默认情况下会对注释进行打包输出,如果在打包文件中不想输出注释内容则可以设置此选项
"compilerOptions":{
"removeComments": true
}
noEmit
- 默认情况下会对代码进行编译,可以看到编译生成的文件,如果不想编译生成文件则可以设置此选项
"compilerOptions":{
"noEmit": true
}
module
- 指定要使用的模块化规范
- 可选值有:none, commonjs, amd, system, umd,es6, es2015, es2020, esnext
noEmitOnError
- 默认情况下语法错误也能进行编译,如果错误不想编译则可以设置此选项
"compilerOptions":{
"noEmitOnError": true,
}
strict
- 开启严格模式,开发中会开启,让程序更严谨
"compilerOptions":{
"strict": true,
}
设置了严格模式后,会对代码进行空值的判断。如果存在空值的可能则需进行下面的处理
let btn = document.querySelector("btn")
// 如果btn为空则不进行事件函数的处理
btn?.onclick=function(){
alert('test')
}
Webpack使用TS[待验证]
- 通常情况下,实际开发中我们都需要使用构建工具对代码进行打包,TS也可以结合构建工具一起使用。
- 简单来说,使用webpack对ts进行编译生成js。
使用步骤如下:
- 使用
npm ini -y
初始化项目 - 安装开发时依赖
npm install -D webpack webpack-cli typescript ts-loader
- 根目录下创建
webpack.config.js
文件
const path = require('path')
module.exports = {
entry: './src/index.ts',
output: {
path: path.resolve(__dirname,'dist'),
filename: 'bundle.js'
},
module:{
rules:[
{
test:/\.ts$/,
use:'ts-loader',
exclude: /node-modules/
}
]
},
/*
默认情况下,xx.ts不能直接使用"import"和"export"的方式 加载或者导出
解决ts文件可以使用"import"或"export"方式加载或导出
*/
resolve:{
extensions: [".ts",".js"]
}
}
- 创建
tsconfig.json
配置文件,指定ts编译时的规则
{
"compilerOptions": {
"module": "ES2015",
"target": "ES2015",
"strict": true
}
}
-
package.json
中的script
属性配置打包命令
{
"script":{
"build": "webpack"
}
}
- 执行打包命令
npm run build
注意
- 在使用import导入文件时不能添加文件名后缀否则会报错。比如: import {n1} from './a'
babel[待验证]
-
JS中有不同的版本,比如:ES5,ES6,ES2020...等等。当我们采用新版本的JS去写代码时,低版本的浏览器无法识别,所以需要有一种可以将新语法的转换成旧版的,这样才能让低版本的浏览器去识别。
-
其中
tsconfig.json
的compilerOptions
属性有target
选项,我们可以指定编译成js的版本,它只能做JS中简单的语法转换,但对于新增的技术它是不支持的(比如:ES6的Promise),这个时候就需要使用到babel
,可以兼容更多的浏览器。 -
babel的作用
- 把新语法转换成旧语法
- 把新的类、对象转换成低版本浏览器支持的类。
- 为了让代码有更好的兼容性,可以在不同的浏览器中使用,使用babel来帮助我们解决兼容性的问题
步骤:
- 安装开发时依赖
cnpm i -D @babel/core @babel/preset-env babel-loader core-js
- @babel/core --核心库
- @babel/preset-env ---预设环境。我们需要兼容不同的浏览器环境,这个模块里面定义好了转换的代码
- babel-loader的作用是将 babel和webpack结合的一款工具
- core-js的作用是模拟js的运行环境,让老版本的浏览器可以使用到新标准的技术。里面装有所有兼容新功能的代码,在开发中我们经常是按需加载
- webpack.config.js配置
module:{
rules:[
{
test:/\.ts$/,
use:[
//多个loader进行处理,则use使用数组的形式
// 多个loader的执行顺序是从后往前。
// ts-loader的作用是将ts转换为js;babel-loader的作用是将js转换为低版本浏览器可识别的js代码
// 如果loader需要详细的配置,则将字符串形式转换为对象的形式
{
loader:"babel-loader",
options:{
// 设置预定义的环境【也就是假设你的代码是要在哪些环境下运行】
presets:[
[
"@babel/preset-env",
{
//指定浏览器的版本
targets:{
// 兼容chrome的58版本
"chrome":"58",
"IE":"11" //也就是说兼容所有低版本的浏览器
},
//指定corejs的版本 【和当前安装的版本一致即可】
"corejs": "3",
// 使用corejs的方式
"useBuiltIns": "usage" //按需加载
}
]
]
}
},
"ts-loader"
]
}
]
}
-
使用上述配置和不使用上述配置,然后设置
tsconfig.json
中的compilerOptions
属性的target
属性配置为ES2015
(这个就是ES6版本),测试ts文件中使用const
定义变量的形式 是否在打包后的js文件中转换。-
不使用上述配置,打包后的js文件中
const
定义的变量【没有】转换成var声明的变量 -
使用上述配置,然后webpack配置
targets
中含有低版本的IE,那么const
定义的变量【会】转换成var声明的变量 -
注意
- 上面使用
const
等普通的ES6语法是没有使用到corejs
;当加载低版本浏览器不能识别的类或对象等情况时会使用到corejs
中封装的代码,这样才能让低版本浏览器识别(比如:Promise)。------corejs只有在下面配置后才起作用
"corejs": "3", "useBuiltIns": "usage"
- 上面使用corejs按需加载后可能还是在IE不能成功运行,因为起打包后生成的js是箭头函数,IE不支持。babel可以将箭头函数转换为浏览器识别的函数。上面报错是因为webpack打包后自带生成箭头函数来处理打包后的js,我们可以告诉webpack使用普通函数打包不要使用箭头函数。
webpack.config.js
配置如下
module.exports = { output: { environment:{ arrowFunction: false } } }
- 上面使用
-