美文网首页TypeScript
TypeScript基础教程

TypeScript基础教程

作者: WebGiser | 来源:发表于2022-02-10 21:44 被阅读0次

安装

1、下载安装nodejs稳定版本
2、使用npm全局安装typescript

npm  i  -g  typescript

3、使用tsc对文件进行编译

tsc  xxx.ts
// 实时监控ts文件变化
tsc  -w

变量类型

// 定义数字
let a : number;
a = 10;


// 定义字符串
let b : string;
b  = 'sss';


// 定义字面量
let str : "male" | "female";
str = "male";
str = "female";

let c : boolean | string;
c = true;
c = "s";


// 定义数组结构声明:1、类型[],2、Array<类型>
let arr : string[];
arr = ['a', 'b', 'c'];
let arr2 : number[];
arr2 = [1, 3, 5];
let arr3 : Array<boolean>;
arr3 = [true, false];


// 定义元祖:元祖就是固定长度的数组
let h : [string, string, number];
h = ['a', 'b', 10]


// 定义对象,设置对象结构的类型声明
let people : {name:string, age?:number, [propName:string]:any};
people = {name: 'aaa', age: 10}
people = {name: 'aaa', age: 10, address: '中国'}


// 定义函数,设置函数结构的类型声明
function sum(a:number, b:number):number{
    return a + b;
}
console.log(sum(1, 2))

let fun : (a:number, b:number)=>number;
fun = function(a, b){
    return a+b;
}


// 定义枚举
enum Gender{
    Male,
    Female
}
let person : {name:string, gender:Gender};
person = {
    name : '',
    gender: Gender.Female
}
console.log(person.gender === Gender.Female)

TS编译文件配置

tsconfig.json

{
    // 包含或排除哪些目录下的ts文件,**表示任意目录,*表示任意文件
    "include": ["./src/**/*"],
    "exclude": [],
    // 编译配置
    "compilerOptions": {
        // ts编译成es的版本
        "target": "ES6",
        // 指定要使用的模块化 
        "module": "system",

        // 指定项目中要使用的库,一般不需要修改
        // "lib": ["DOM"],

        // 指定编译后文件所在的目录
        "outDir": "./dist",
        // 将全局作用域的所有代码合并为一个文件
        // "outFile": "./dist/app.js",

        // 是否对js文件进行编译,默认是false
        "allowJs": false,
        // 是否检查js代码是否符合规范,默认是false
        "checkJs": true,
        // 是否移除编译后的注释
        "removeComments": false,
        // 是否不生成编译后的文件。可以只检查
        "noEmit": false,
        "noEmitOnError": true,

        // 所有严格检查的总开关
        "strict": true,

        // 是否使用严格模式,默认是false
        "alwaysStrict": true,
        // 不指定变量类型时,是否默认是any
        "noImplicitAny": false,
        // 类型不明的this检查
        "noImplicitThis": true,

        // 严格检查空值
        "strictNullChecks": true
    }
}

webpack打包

1、创建 02 空文件夹

2、初始化 package.json 文件

npm  init  -y

3、安装相关依赖

cnpm i -D webpack webpack-cli typescript ts-loader

cnpm i -D html-webpack-plugin  
cnpm i -D webpack-dev-server
cnpm i -D clean-webpack-plugin

cnpm i -D @babel/core @babel/preset-env babel-loader core-js

4、创建相关配置文件
package.json

{
  "name": "02",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "build": "webpack",
    "start": "webpack serve --open chrome.exe"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "@babel/core": "^7.17.2",
    "@babel/preset-env": "^7.16.11",
    "babel-loader": "^8.2.3",
    "clean-webpack-plugin": "^4.0.0",
    "core-js": "^3.21.0",
    "html-webpack-plugin": "^5.5.0",
    "ts-loader": "^9.2.6",
    "typescript": "^4.5.5",
    "webpack": "^5.68.0",
    "webpack-cli": "^4.9.2",
    "webpack-dev-server": "^4.7.4"
  }
}

webpack.config.js

//引入一个包
const path = require('path');
// 引入 html-webpack-plugin 插件
const HtmlWebpackPlugin = require('html-webpack-plugin');
// 引入 clean-webpack-plugin 插件
const {CleanWebpackPlugin} = require('clean-webpack-plugin');


// webpack中的所有配置信息都应写在 module.exports中
module.exports = {
    // 指定入口文件
    "entry": "./src/index.ts",
    // 指定打包文件所在目录
    "output": {
        path: path.resolve(__dirname, "dist"),
        // 打包后文件的名称
        filename: "app.js",
        // webpack是否使用箭头函数
        environment: {
            arrowFunction: false
        }
    },
    // mode: "development",
    // 指定webpack打包时要使用的模块
    "module": {
        // 指定要加载的规则
        rules: [
            {
                // 规则生效的文件
                test: /\.ts$/,
                use: [
                    {
                        loader: "babel-loader",
                        options: {
                            presets: [
                                [
                                    "@babel/preset-env",
                                    {
                                        // 要兼容的目标浏览器
                                        targets: {
                                            "chrome": "88",
                                            "ie": "11"
                                        },
                                        // 指定corejs的版本
                                        "corejs": "3",
                                        // 使用corejs方式:usage表示按需加载
                                        "useBuiltIns": "usage"
                                    }
                                ]
                            ]
                        }
                    },
                    {
                        loader: "ts-loader"
                    }
                ],
                exclude: /node_modules/
            }
        ]
    },
    plugins:[
        new CleanWebpackPlugin(),
        new HtmlWebpackPlugin({
            // title: "自定义的title"
            template: './src/index.html'
        })
    ],
    // 设置引用的模块
    resolve: {
        extensions: ['.ts', '.js']
    }
}

tsconfig.json

{
    "compilerOptions": {
        "module": "ES2015",
        "target": "ES2015",
        "strict": true
    }
}

5、创建业务代码
src/index.html

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8" />
        <title>自定义的title</title>
    </head>
    <body>hello world</body>
</html>

src/index.ts

import {printHello} from './test'
printHello();

function sum (num1:number, num2:number):number{
    return num1+num2;
}
console.log(sum(3,5))

const num = 30;
console.log(num);

console.log(Promise)

src/test.ts

function printHello(){
    console.log('hello!')
}

export {printHello}

最后的项目结构如下


image.png

1、person.ts

// 定义类,主要包含2大部分:属性、方法
class Person{
    // 实例属性
    name:string = "孙悟空";
    // 静态属性
    static age:number = 18;
    // 只读属性,无法修改
    readonly address:string = "花果山";
    // 只读静态属性,无法修改
    static readonly task:string = "西天取经";

    // 私有属性(public、protected、private)
    private _height:number = 500;

    // getHeight(){
    //     return this._height;
    // }
    // setHeight(height:number){
    //     this._height = height;
    // }

    get height(){
        return this._height;
    }
    set height(height:number){
        this._height = height;
    }

    // 定义实例方法
    sayHello(){
        console.log("hello 大家好!");
    }

    // 定义静态方法
    static sayHello2(){
        console.log("hello2 大家好!");
    }
}


// 测试属性
const person = new Person();
console.log(person);
console.log(person.name);
console.log(Person.age);

// 测试方法
person.sayHello();
Person.sayHello2();

// 修改私有属性
// person.setHeight(100);
person.height = 100;
// console.log(person);

2、dog.ts

// 定义类,主要包含2大部分:属性、方法
class Dog{
    name:string;
    age:number;

    // 构造函数
    constructor(name:string, age:number){
        this.name = name;
        this.age = age;
    }

    // 定义实例方法
    bark(){
        console.log(this);
        console.log("汪汪汪!!!");
    }
}

const dog = new Dog("旺财", 3);
console.log(dog);
dog.bark();

3、interface.ts

// 接口: 包含属性结构和抽象方法,定义了规范
interface myInter{
    name:string;
    age:number;
    sayHello():void;
}

class myClass implements myInter{
    name:string;
    age:number;

    constructor(name:string, age:number){
        this.name = name;
        this.age = age;
    }

    sayHello(): void {
        console.log("----------");
    }
}

const my = new myClass("张三", 10);
console.log(my);

4、extends.ts

// 继承、抽象
// 父抽象类
abstract class Animal{
    name:string;
    age:number;

    constructor(name:string, age:number){
        this.name = name;
        this.age = age;
    }

    // 抽象方法
    abstract sayHello():void;
}

// 子类
class Cat extends Animal{
    // 实现父类中的抽象方法
    sayHello(): void {
        console.log("喵喵喵喵!!!")
    }
}

const cat = new Cat("小花", 3);
console.log(cat);
cat.sayHello();

5、T.ts

// 泛型:在定义函数或类时,如果遇到类型不明确就可以使用泛型

// 函数泛型
function fn<T>(a:T):T{
    return a;
}
console.log(fn(10));
console.log(fn<string>("hello"));

function fn2<T, K>(a:T, b:K):T{
    return a;
}
console.log(fn2<number, string>(10, "hello"));


// 接口泛型
interface Inter{
    length:number;
}
class People implements Inter{
    constructor(public length:number){}
}
function fn3<T extends Inter>(a:T):number{
    return a.length;
}
console.log(fn3(new People(10)));


// 类泛型
class Computer<T>{
    name: T;
    age: number;
    constructor(name:T, age:number){
        this.name = name;
        this.age = age;
    }
}
const computer = new Computer<string>("联想", 3);
console.log(computer);

6、index.html

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8" />
        <title>自定义的title</title>
        <script src="./dist/person.js"></script>
        <script src="./dist/dog.js"></script>
        <script src="./dist/extends.js"></script>
        <script src="./dist/interface.js"></script>
        <script src="./dist/T.js"></script>
    </head>
    <body>hello world</body>
</html>

7、tsconfig.json

{
    "include": ["./src/**/*"],
    "compilerOptions": {
        "module": "ES2015",
        "target": "ES2015",
        "strict": true,
        "outDir": "./dist",
        "noEmitOnError": true
    }
}
1.jpg

贪吃蛇项目

1、将webpack打包中的3个配置文件(package.json、tsconfig.json、webpack.config.js)拷贝到新文件夹中,并执行 cnpm i 安装依赖
2、安装新的依赖

cnpm i -D less less-loader css-loader style-loader
cnpm i -D postcss postcss-loader postcss-preset-env

3、项目结构如下


image.png

4、package.json

{
  "name": "02",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "build": "webpack",
    "start": "webpack serve --open chrome.exe"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "@babel/core": "^7.17.2",
    "@babel/preset-env": "^7.16.11",
    "babel-loader": "^8.2.3",
    "clean-webpack-plugin": "^4.0.0",
    "core-js": "^3.21.0",
    "css-loader": "^6.6.0",
    "html-webpack-plugin": "^5.5.0",
    "less": "^4.1.2",
    "less-loader": "^10.2.0",
    "postcss": "^8.4.6",
    "postcss-loader": "^6.2.1",
    "postcss-preset-env": "^7.3.1",
    "style-loader": "^3.3.1",
    "ts-loader": "^9.2.6",
    "typescript": "^4.5.5",
    "webpack": "^5.68.0",
    "webpack-cli": "^4.9.2",
    "webpack-dev-server": "^4.7.4"
  }
}

5、tsconfig.json

{
    "compilerOptions": {
        "module": "ES2015",
        "target": "ES2015",
        "strict": false,
        "noEmitOnError": true
    }
}

6、webpack.config.js

//引入一个包
const path = require('path');
// 引入 html-webpack-plugin 插件
const HtmlWebpackPlugin = require('html-webpack-plugin');
// 引入 clean-webpack-plugin 插件
const {CleanWebpackPlugin} = require('clean-webpack-plugin');


// webpack中的所有配置信息都应写在 module.exports中
module.exports = {
    // 指定入口文件
    "entry": "./src/index.ts",
    // 指定打包文件所在目录
    "output": {
        path: path.resolve(__dirname, "dist"),
        // 打包后文件的名称
        filename: "app.js",
        // webpack是否使用箭头函数、const.(为了兼容IE等浏览器)
        environment: {
            arrowFunction: false,
            const: false
        }
    },
    // mode: "development",
    // 指定webpack打包时要使用的模块
    "module": {
        // 指定要加载的规则
        rules: [
            {
                // 规则生效的文件
                test: /\.ts$/,
                use: [
                    {
                        loader: "babel-loader",
                        options: {
                            presets: [
                                [
                                    "@babel/preset-env",
                                    {
                                        // 要兼容的目标浏览器
                                        targets: {
                                            "chrome": "88",
                                            "ie": "11"
                                        },
                                        // 指定corejs的版本
                                        "corejs": "3",
                                        // 使用corejs方式:usage表示按需加载
                                        "useBuiltIns": "usage"
                                    }
                                ]
                            ]
                        }
                    },
                    {
                        loader: "ts-loader"
                    }
                ],
                exclude: /node_modules/
            },
            {
                test: /\.less$/,
                use: [
                    "style-loader", 
                    "css-loader", 
                    {
                        loader: "postcss-loader",
                        options: {
                            postcssOptions: {
                                plugins: [
                                    [
                                        "postcss-preset-env",
                                        {
                                            browsers: "last 2 versions"
                                        }
                                    ]
                                ]
                            }
                        }
                    },
                    "less-loader"
                ]
            }
        ]
    },
    plugins:[
        new CleanWebpackPlugin(),
        new HtmlWebpackPlugin({
            // title: "自定义的title"
            template: './src/index.html'
        })
    ],
    // 设置引用的模块
    resolve: {
        extensions: ['.ts', '.js']
    }
}

7、index.html

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8" />
        <title>贪吃蛇</title>
    </head>
    <body>
        <div id="main">
            <div id="stage">
                <!-- 设置蛇 -->
                <div id="snake">
                    <!-- 蛇的各部分 -->
                    <div>

                    </div>
                </div>

                <!-- 食物 -->
                <div id="food">
                    <div></div>
                    <div></div>
                    <div></div>
                    <div></div>
                </div>
            </div>
            <div id="score-panel">
                <div>
                    SCORE:<span id="score">0</span>
                </div>
                <div>
                    LEVEL:<span id="level">1</span>
                </div>
            </div>
        </div>
    </body>
</html>

8、index.ts

// 引入样式
import './style/index.less';

import GameControl from './modules/GameControl';
new GameControl();

9、src/style/index.less

// 设置变量
@bg-color: #b7d4a8;

// 清除默认样式
*{
    margin: 0;
    padding: 0;
    // 改变盒子模型的计算方式
    box-sizing: border-box;
}

body{
    font: bold 20px "Courier";
}

// 设置主窗口的样式
#main{
    width: 360px;
    height: 420px;
    background-color: @bg-color;
    margin: 100px auto;
    border: 10px solid black;
    border-radius: 10px;
    // 开启弹性盒模型
    display: flex;
    // 设置主轴的方向
    flex-flow: column;
    // 设置侧轴的对齐方式
    align-items: center;
    // 设置主轴的对齐方式
    justify-content: space-around;

    // 游戏舞台
    #stage{
        width: 304px;
        height: 304px;
        border: 2px solid black;
        // 开启相对定位
        position: relative;

        // 设置蛇的样式
        #snake{
            &>div{
                width: 10px;
                height: 10px;
                background-color: #000000;
                border: 1px solid @bg-color;
                // 开启绝对定位
                position: absolute;
            }
        }

        // 设置食物样式
        #food{
            position: absolute;
            width: 10px;
            height: 10px;
            left: 40px;
            top: 100px;
            display: flex;
            // 设置主轴为横轴,wrap表示会自动换行
            flex-flow: row wrap;
            justify-content: space-between;
            align-content: space-between;
            &>div{
                width: 4px;
                height: 4px;
                background-color: black;
                transform: rotate(45deg);
            }
        }
    }

    // 记分牌
    #score-panel{
        width: 300px;
        display: flex;
        // 设置主轴的对齐方式
        justify-content: space-between;
    }
}

10、src/modules/Foods.ts

// 定义食物类
class Food{
    // 定义一个属性表示食物对应的div
    element: HTMLElement;

    constructor(){
        // 获取页面中food元素,并赋值给element
        this.element = document.getElementById('food')!;
    }

    // 获取食物x轴坐标的方法
    get X(){
        return this.element.offsetLeft;
    }
     // 获取食物y轴坐标的方法
     get Y(){
        return this.element.offsetTop;
    }

    // 随机修改食物位置
    change(){
        // 随机数,0-290之间且步长为10(蛇每次移动一格,10px)
        // Math.round: 四舍五入。Math.random:0-1随机数(不包含0和1)
        let top = Math.round(Math.random() * 29) * 10;
        let left = Math.round(Math.random() * 29) * 10;
        this.element.style.left = left+'px';
        this.element.style.top = top+'px';
    }
}

// const food = new Food();
// console.log(food.X, food.Y);
// setInterval(()=>{
//     food.change();
//     console.log(food.X, food.Y);
// }, 1000)

export default Food;

11、GameControl.ts

import Snake from "./Snake";
import Food from "./Food";
import ScorePanel from "./ScorePanel";

// 游戏控制器,控制其他的所有类
class GameControl {
    // 蛇
    snake: Snake;
    // 食物
    food: Food;
    // 记分牌
    scorePanel: ScorePanel;
    // 存储蛇的移动方向,即键盘的按键方向
    direction: string = "";
    // 游戏是否结束
    isLive: boolean = true;

    constructor() {
        this.snake = new Snake();
        this.food = new Food();
        this.scorePanel = new ScorePanel(10, 10);
        this.init();
    }

    // 游戏的初始化方法,调用后游戏开始
    init() {
        // 绑定键盘按键按下事件
        document.addEventListener("keydown", this.keydownHandler.bind(this));
        this.run();
    }

    // 创建键盘按键按下的响应函数(ArrowUp、ArrowDown、ArrowLeft、ArrowRight)
    keydownHandler(event: KeyboardEvent) {
        this.direction = event.key;
    }

    // 根据direction控制蛇移动
    run() {
        let X = this.snake.X;
        let Y = this.snake.Y;
        switch (this.direction) {
            case "ArrowUp":
            case "Up":
                Y -= 10;
                break;
            case "ArrowDown":
            case "Down":
                Y += 10;
                break;
            case "ArrowLeft":
            case "Left":
                X -= 10;
                break;
            case "ArrowRight":
            case "Right":
                X += 10;
                break;
        }
        // 检查蛇是否吃到食物
        this.checkEat(X, Y);
        // 修改蛇的xy
        try {
            this.snake.X = X;
            this.snake.Y = Y;
        } catch (e) {
            alert(e.message + " GAME OVER!");
            this.isLive = false;
        }

        // 开启一个定时调用
        this.isLive &&
            setTimeout(
                this.run.bind(this),
                300 - (this.scorePanel.level - 1) * 30
            );
    }

    // 检查蛇是否吃到食物
    checkEat(X: number, Y: number) {
        if (X === this.food.X && Y === this.food.Y) {
            this.food.change();
            this.scorePanel.addScore();
            this.snake.addBody();
        }
    }
}

export default GameControl;

12、ScorePanel.ts

// 定义记分牌类
class ScorePanel{
    score:number = 0;
    level:number = 1;
    scoreElem: HTMLElement;
    levelElem: HTMLElement;
    maxLevel:number;
    upScore:number;

    constructor(maxLevel:number=10, upScore:number=10){
        this.scoreElem = document.getElementById('score')!;
        this.levelElem = document.getElementById('level')!;
        this.maxLevel = maxLevel;
        this.upScore = upScore;
    }

    // 加分方法
    addScore(){
        this.score++;
        this.scoreElem.innerHTML = this.score+'';
        if(this.score % this.upScore === 0){
            this.levelUp();
        }
    }

    // 升级方法
    levelUp(){
        if(this.level < this.maxLevel){
            this.level++;
            this.levelElem.innerHTML = this.level+'';
        }
    }
}

// const score = new ScorePanel();
// setInterval(()=>{
//     score.addScore();
// }, 500)

export default ScorePanel;

13、Snake.ts

class Snake{
    // 表示蛇头
    head:HTMLElement;
    // 蛇的身体(包括蛇头)
    bodies:HTMLCollection;
    // 获取蛇的容器
    element:HTMLElement;

    constructor(){
        this.element = document.getElementById('snake')!;
        this.head = document.querySelector('#snake > div')!;
        this.bodies = this.element.getElementsByTagName('div');
    }

    // 获取蛇头的坐标
    get X(){
        return this.head.offsetLeft;
    }
    get Y(){
        return this.head.offsetTop;
    }

    // 设置蛇头的坐标
    set X(value:number){
        // 如果新值和旧值一样,不再修改
        if(this.X === value){
            return;
        }
        // 蛇是否撞墙
        if(value < 0 || value > 290){
            throw new Error("蛇撞墙了!");
        }
        // 蛇在水平移动时,不能掉头
        if(this.bodies[1] && (this.bodies[1] as HTMLElement).offsetLeft === value){
            if(value > this.X){
                value = this.X - 10;
            }else{
                value = this.X + 10;
            }
        }
        this.moveBody();
        this.head.style.left = value+"px";
        this.checkHeadBody();
    }
    set Y(value:number){
        if(this.Y === value){
            return;
        }
        // 蛇是否撞墙
        if(value < 0 || value > 290){
            throw new Error("蛇撞墙了!");
        }
        // 蛇在竖直移动时,不能掉头
        if(this.bodies[1] && (this.bodies[1] as HTMLElement).offsetTop === value){
            if(value > this.Y){
                value = this.Y - 10;
            }else{
                value = this.Y + 10;
            }
        }
        this.moveBody();
        this.head.style.top = value+"px";
        this.checkHeadBody();
    }

    // 蛇增加身体的方法
    addBody(){
        this.element.insertAdjacentHTML("beforeend", "<div></div>");
    }

    // 蛇移动身体
    moveBody(){
        // 将后边的身体设置为前边的身体
        // 第3节等于第2节位置,第2节等于第1节位置,第1节等于蛇头的位置
        for(let i=this.bodies.length-1; i>0; i--){
            let X = (this.bodies[i-1] as HTMLElement).offsetLeft;
            let Y = (this.bodies[i-1] as HTMLElement).offsetTop;
            (this.bodies[i] as HTMLElement).style.left = X+"px";
            (this.bodies[i] as HTMLElement).style.top = Y+"px";
        }
    }

    // 检查蛇的头部与身体是否相撞
    checkHeadBody(){
        for(let i=1; i<this.bodies.length; i++){
            let bd = this.bodies[i] as HTMLElement;
            if(this.X === bd.offsetLeft && this.Y === bd.offsetTop){
                throw new Error("蛇撞到自己了!");
            }
        }
    }
}

export default Snake;

14、npm run build 打包生成 dist文件夹(app.js、index.html),然后浏览器直接打开index.html即可看到效果


image.png

相关文章

网友评论

    本文标题:TypeScript基础教程

    本文链接:https://www.haomeiwen.com/subject/vblnkrtx.html