提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
TS基础-学习笔记
配置环境
(一)安装nodejs(可跳过)
node.js要先下载;直接去官网下载(建议下载稳定版),然后去配置环境就可以了:
nodejs中文网 选择长期稳定版,或根据自己需要,下载(.msi文件
点击安装)就可以了
查看nodejs是否安装成功
node -v
(二)安装nvm(可选择)
参考之前的文章 七、nvm
使用npm全局安装typescript
(三)正式开始
- 安装typescript
控制台输入
npm install -g typescript
输入tsc检查是否安装成功
- 项目初始化-生成
package.json
npm init //初始化
//或者使用
npm init -y //默认全部
如果已经有.ts
文件 使用tsc进行编译
tsc XXX.ts
tsc -W //开启监视,每次保存都会自动编译
添加/配置 tsconfig.json
上面说的编译中-W
只能监视当前文件,如果想要监视整个目录下的文件,需要在ts配置文件tsconfig.json
中添加
{
"compilerOptions": {
"outDir": "./dist/",
"module": "ES6", //模块化规范
"target": "ES6",
"strict": true,
// "jsx": "react"
},
"include": [
"./src/**/*"
],
}
之后运行tsc -W
就可以监视所有文件下的ts文件.
tsconifg.json文件是ts的配置文件也是可以通过命令生成
tsc --init
执行命令之后生成的文件内容可以根据自己的需要修改,生成内容如:
Ts安装依赖(可跳过)
首先确保已经安装了Webpack;
webpack可以将所有代码和可选择的将依赖捆绑成单独的.js文件
npm install -g webpack
添加开发依赖
- awesome-typescript-loader 使webpack使用typescript的标准配置tsconfig.json编译ts代码;
- source-map-loader 使用ts输出的sourcemap文件告诉webpack何时生成自己的sourcemaps;
npm install --save-dev typescript awesome-typescript-loader source-map-loader
创建tsconfig.json文件
包含输入文件列表和编译选项。在工程根目录下新建文件tsconfig.json
{
"compilerOptions": {
"outDir": "./dist/",
"sourceMap": true,
"noImplicitAny": true,
"module": "commonjs",
"target": "ES6",
},
"include": [
"./src/**/*"
],
"outDir": "./dist",
"outFile": "./dist/app.js", //文件合并
"allowJs": true,
"noEmitOnError": true,
"alwaysStrict": true,//开启严格模式
}
创建webpack配置文件
在项目根目录下创建webpack.config.js文件
module.exports = {
entry: "./src/index.tsx",
output: {
filename: "bundle.js",
path: __dirname + "/dist"
},
// Enable sourcemaps for debugging webpack's output.
devtool: "source-map",
resolve: {
// Add '.ts' and '.tsx' as resolvable extensions.
extensions: [".ts", ".tsx", ".js", ".json"]
},
module: {
rules: [
// All files with a '.ts' or '.tsx' extension will be handled by 'awesome-typescript-loader'.
{ test: /\.tsx?$/, loader: "awesome-typescript-loader" },
// All output '.js' files will have any sourcemaps re-processed by 'source-map-loader'.
{ enforce: "pre", test: /\.js$/, loader: "source-map-loader" }
]
},
// 当导入路径与以下其中一个匹配的模块时,只需假设存在相应的全局变量并使用该全局变量即可。
//这一点很重要,因为它允许我们避免捆绑所有的依赖项,从而允许浏览器在构建之间缓存这些库。
externals: {//命名空间
// "react": "React",
//"react-dom": "ReactDOM"
},
};
一、类简介
对象中主要包含两个部分: 属性、方法
(一) 属性
1.实例属性 通过定义实例对象进行调用 如name属性;
2.静态属性 通过类调用 如 Person.age
class Person {
// 定义实例属性 == 可被修改
name: string = '张三';
// 定义静态属性
static age: number = 18;
readonly gender: string = '男';//只读属性
}
const per = new Person();//创建实例对象
console.log(per.gender);
console.log(per.name);//张三
console.log(Person.age)//调用静态属性
per.name = '李四';
console.log(per.name);//调用实例属性 李四
(二) 方法
创建方法
// 定义方法
// 类方法 可直接通过类调用
static run() {
console.log("I can run");
}
//实例方法
eat() {
console.log("I can eat");
}
调用方法
// 调用类方法
Person.run();//I can run
// 调用实例方法
per.eat();//I can eat
二、构造函数和this
构造函数,在对象创建时被调用
构造函数中 this表示当前实例
当前对象 == 当前新建的对象 谁new的就是谁
//构造函数 == 在对象创建时被调用
constructor(){
console.log("constructor is run")
console.log(this);//this 表示当前的实例
}
可以通过this 在新建的对象中添加属性
三、继承
使用继承后,子类继承所有父类的方法和属性
可以将多个类中的共有代码,写在同一个父类中,所有的子类可以同时拥有父类中的属性和方法.
可以在不修改原来代码的基础上,增加新的方法;
方法重写-->如果在子类中增加与父类相同的方法名,子类会覆盖父类的方法;
方法重写
四、super关键字
super代表当前类的父类
五、抽象类
abstract 表示抽象
抽象类中不能创建实例对象;只能被继承
抽象类中可以添加抽象方法
抽象方法没有方法体
在继承的时候必须实现抽象类中的抽象方法;
六、接口
接口定义了一个规范,是对类的一种规范限制;没有实际值;实现接口必须满足接口中的类和方法
接口用来定义一个类结构;
定义一个类中应该包含哪些属性和方法;
接口也可以被当成类型声明使用
接口在被定义类的时候限制类的结构;
接口的所有属性都不能有实际的值,只能定义对象的结构,而不考虑实际的值;
接口中的所有方法,都是抽象方法;
对象和接口的区别
- 对象声明,在方法中只能声明一次,接口可以被定义多个
定义类时实现接口
七、属性的封装
ts可以在属性前添加属性修饰符
public 公共的 可以在任何位置访问(修改) 默认(大家)
private 私有的 只能在类内部访问(自己)
protected 受保护的 可以在当前类中和在被继承的时候被访问(自己和子类)
为了防止数据被恶意修改,属性被封装到 存储器里(getter setter);
因为private属性是私有的不能被类以外的地方调用;但是可以通过存储器被暴露出去.
此时可以根据自己的需求,通过get set对方法中的属性暴露.为后续修改提供限制进行修改;
class Cup {
private owner: string; //只能在类中被调用
private name: string;
constructor(name: string, owner: string) {
this.name = name;
this.owner = owner;
}
/** 属性存储器 */
//读取属性
getName() {
return this.name;
}
// 设置属性
setName(value: string) {
this.name = value;
}
}
const cup = new Cup('早餐杯', '可爱型');
console.log(cup.getName())//早餐杯
cup.setName('水杯');
console.log(cup.getName())//水杯
上述方式增加了书写代码的数量,每一次都需要带方法名.
为了使用户体验更加良好,ts提供了一种特有的方式进行封装
方法不同,定义和调用的方式也不同,注意区分
private _owner: string;
private _name: string;
constructor(name: string, owner: string) {
this._name = name;
this._owner = owner;
}
get owner() {
return this._owner;
}
set owner(value: string) {
this._owner = value;
}
get name() {
return this._name;
}
set name(value: string) {
this._name = value;
}
const cup = new Cup('早餐杯', '可爱型');
console.log(cup.name)//早餐杯
cup.name = '水杯';//赋值
console.log(cup.name)//水杯
注意 get后的方法名不能和属性名重名
属性少的类,可以将属性直接写道构造函数中;节省书写步骤.
//可以直接将属性写在构造函数中
class C {
constructor(public name: string, public gender: string) { }
}
const c = new C('张三', '男');
console.log(c);
console.log(c.name)//张三
上述方法等价于
// 一个是在原型上添加方法,一个是在原型上定义属性; 属性和get方法不能崇明
name: string;
gender: string;
constructor(name: string, gender: string) {
this.name= name;
this.gender= owner;
}
八、泛型
定义函数/类时,如果类型不明确,可以使用泛型.
定义泛型<*> *可以是任何字母,表示任意类型
定义一个参数类型:
//定义泛型<T> a的类型是T :T(返回值是T类型)
function fn<T>(a: T): T {
return a;
}
fn(10);//利用函数的自动推断,此时T指number型
fn<string>('hello')//指定泛型;当类型复杂,可以指定
定义多个参数类型
// 泛型可以同时指定多个
function fn2<T, K>(a: T, b: K): T {
console.log(b)
return a;
}
fn2<number, string>(12, '天天') //打印出天天
泛型可以继承接口实现类
interface lent {
length: number;
}
// T extends lent 泛型T必须是lent的实现类(子类)
function fn3<T extends lent>(a:T):number{
return a.length;
}
fn3('123')
// fn3(123)//会报错->不可转换的参数类型
fn3({ length: 10 })
泛型可以用类定义
class fn4<T>
{
name: T;
constructor(name: T) {
this.name = name;
}
}
const f4 = new fn4<string>('张安')
console.log(f4.name) //张安
总结
这些是我在跟着网课学的时候自己敲下来的总结笔记,作为自己的笔记记录.如果能帮到你们当然也很好.
如果有什么错误和不足,欢迎补充.
最后的泛型我也是听的一知半解,跟着做了项目也没有用到这个
🕳 在get set中定义的时候 显示说标识符重复
其实很好理解,就相当于说 get 是一种声明说此时是get方法.后面的是方法名称.
比如name在上面已经被定义过了,后面的方法名称写name当然会报错.
get里面return 的值是属性的值就可以了.
所以在get name的方法体中,return的是属性名_name.