这是我参与更文挑战的第4天,活动详情查看: 更文挑战
1, 实战前奏
实例属性必须通过实例去访问
静态属性必须通过类去访问
class Person1 {
// 定义实例属性
name: string = 'zlm';
// 在属性前面使用static 关键字定义的为: 静态属性,是类的方法
static age: number = 12;
// 只读属性,无法修改
readonly sex: boolean = false;
sayHello() {
console.log("hello world")
}
}
const person = new Person1()
console.log(person.name)
console.log(Person1.age)
console.log(person.sayHello())
构造函数:在 new Person()的时候,constructor执行
在实例方法中,this就表示当前的实例
可以通过this 向新建的对象中添加属性
class Dog {
name: string;
age: number;
// 构造函数,在对象创建的时候调用,
constructor(name:string, age:number) {
this.name = name;
this.age = age;
}
bark() {
alert(123)
}
}
const dog = new Dog('小河', 4)
继承:使用继承之后,子类将会拥有所有父类的方法和属性
重写:如果子类中添加类父类相同的方法,父类会被覆盖,这叫重写
一个子类想调用父类的方法: super.sayHello()
子类如果写了构造函数,必须要调用super()
抽象类:以abstract开头的类是抽象类,抽象类和其他区别: 抽象类不能用来创建对象,抽象类是专门用来继承的类, 抽象方法,没有方法体,子类必须对抽象方法进行实现
**接口:**用来定义一个类结构,定义一个类中应该包含哪些属性和方法,同时也可以当成类型声明去使用
type myType2 = {
name: string,
age: number
}
interface myInterface {
name: string;
age: number
}
const Obj:myType2 = {
name: 'zlm',
age: 19
}
const Obj2:myInterface = {
name: 'zlm',
age: 20
}
Type 和 interface 可以同样的使用
Type 和 interface的区别: 接口可以限制类的结构,接口只定义,不能有实际的值,
**实现接口 ** :必须实现接口中所有的方法
class myInter implements myInterface {
name: string;
age: number
constructor(name: string, age: number) {
this.name = name
this.age = age
}
}
语法糖:
class myInter implements myInterface {
constructor(public name: string, public age: number) {
this.name = name
this.age = age
}
}
泛型: 遇到类型不明确的就可以使用泛型
// 不规范的写法
function fnn(a:any): any {
return a;
}
// 定义一个泛型T 来实现
function fnnn<T>(a: T): T {
return a;
}
function fun<T,K>(a:T, b:K) :T {
return a;
}
// 对泛型进行控制
interface Inter {
length: number;
}
// 表示泛型T继承接口Inter, 实现类
function fn3<T extends Inter>(a: T): number {
return a.length
}
2,项目实战
下面是一个贪吃蛇的代码,还没有完全实现,一遍学习一遍开发,持续更新
样式文件:index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<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="socre-panel">
<div>
SCORE: <span id="score">0</span>
</div>
<div>
LEVEL: <span id="level">1</span>
</div>
</div>
</div>
</body>
</html>
CSS文件
// 设置颜色变量
@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;
margin: 0 auto;
position: relative;
// 设置蛇的样式
#snake {
&>div {
width: 10px;
height: 10px;
background-color: #000;
border: 1px solid @bg-color;
// 开启绝对定位
position: absolute;
}
}
#food {
width: 10px;
height: 10px;
position: absolute;
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);
}
}
}
// 计分牌
#socre-panel {
width: 300px;
display: flex;
justify-content: space-around;
}
}
TS文件
// 引入央视
import './style/index.less'
// 定义食物类
class Food {
// 定义一个食物所对应的元素
element: HTMLElement;
constructor() {
this.element = document.getElementById('food')!; // 加!表示ID不可能为空
}
// 获取食物X轴坐标
get X() {
return this.element.offsetLeft
}
// 获取食物Y轴坐标
get Y() {
return this.element.offsetTop
}
// 修改食物的位置
change() {
// 生成一个随机数字, 最大290, 最小0, 并且是10的整数倍
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)
food.change()
console.log(food.X, food.Y)
// 定义计分牌类
class ScorePanel {
score = 0;
level = 1;
scoreEle: HTMLElement;
levelEle: HTMLElement;
constructor() {
this.scoreEle = document.getElementById('score')!;
this.levelEle = document.getElementById('level')!;
}
// 设置加分方法
addScore() {
this.score ++;
this.scoreEle.innerHTML = ++this.score + '';
}
// 升级的方法
levelUp() {
if(this.level < 10) {
this.levelEle.innerHTML = ++this.level + '';
}
}
}
附上webpack的配置文件
const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const { CleanWebpackPlugin } = require('clean-webpack-plugin')
// webpack 中的所有配置信息都应该写在module.exports中
module.exports = {
// 指定入口文件
entry: './src/index.ts',
// 指定打包文件所在的目录
output: {
// 打包后的文件
filename: "bundle.js",
// 指定打包文件的目录
path: path.resolve(__dirname, 'dist'),
// environment: { // 配置打包环境,,告诉webpack不用箭头函数
// arrowFunction: true, // 不用箭头函数
// const: false
// }
},
// 指定webpack 打包时要使用的模块
module: {
// 指定加载的规则
rules: [
{
test: /\.ts$/, // test指定的是规则生效的文件
// 要使用的loader
use: [
// 配置babel
{
// 指定加载去
loader: "babel-loader",
// 设置babel
options: {
// 设置预定义的环境
presets: [
[
// 指定环境的插件
"@babel/preset-env",
// 配置信息
{
// 要兼容的目标浏览器
targets: {
"chrome": "88",
},
// 指定corejs的版本
"corejs": "3",
// 使用corejs的方法,"usage" 表示按需加载
"useBuiltIns": "usage"
}
]
]
}
},
'ts-loader'
],
exclude: /node_modules/ // 要排查的文件
},
// 设置less 文件的处理
{
test: /\.less$/,
use: [
"style-loader",
"css-loader",
// 引入postcss
{
loader: "postcss-loader",
options: {
postcssOptions: [
[
"postcss-preset-env",
{
browsers: 'last 2 versions'
}
]
]
}
},
"less-loader"
]
}
]
},
// 配置webpack 插件
plugins: [
new CleanWebpackPlugin(),
new HtmlWebpackPlugin({
title: '这是自定义Title',
template: "./src/index.html"
})
],
// 用来设置引入模块
resolve: {
extensions: ['.ts', '.js']
}
}
后话
这是typeScript的实战笔记,目前这个游戏还在学习开发中,后续会持续更新,并附上完整的github地址