# 初始化项目
首先 npm init 进行初始化工程,然后使用 tsc --init, 进行初始化 ts 的配置; 然后安装 npm install typescript ts-node -D,配置 package.json "dev": "ts-node ./src/crowller.ts"
获取网页内容可以使用 superagent 库,进行安装: npm install superagent
通过 cheerio 库,类似 jQuery 的语法,获取 html 页面各个区块的内容,安装: npm install cheerio --save
# 项目编译
在 package.json 中配置命令:"build": "tsc" 意思就是编译所有的 ts 文件,可以在 tsc 后面指定编译的文件
编译后会将编译后的 js 文件放在 ts 文件一起,我们可以通过配置 tsconfig.json 将编译后的文件统一放在 build 文件夹中:
"outDir": "./build",
如果我们需要实时进行编译我们的代码,类似热更新,需要配置:
"build": "tsc -w"
安装 nodemon ,监控整个项目文件变化,然后执行命令,然后进行配置 package.json, 也就是监听到文件变化就执行 crowller 脚本, nodemonConfig 中的配置意思是,忽略 data 文件夹下面的文件变化; nodemon 不监听 ts 文件的变化
"scripts": {
"build": "tsc -w",
"start": "nodemon node ./build/crowller.js"
},
"nodemonConfig": {
"ignore": ["data/*"]
},
这样在两个命令行去运行上面的两个命令,可以避免我们每次去运行命令编译。
上面的配置需要运行两个命令才能进行监听文件,进行自动编译执行,我们可以使用 concurrently 包(并行执行两个命令),来只运行一次命令就可以执行上面的两个操作; 首先进行安装:npm install concurrently -D,然后修改 package.json:
"scripts": {
"dev:build": "tsc -w",
"dev:start": "nodemon node ./build/crowller.js",
"dev": "concurrently npm:dev:*"
},
上面的配置存在问题,如果第一次没有编译结果,build 文件夹中没有 js 文件,会报错,我们可以在运行监听文件变化的时候,首先执行一定编译,修改上面的配置:
"dev": "tsc && concurrently npm:dev:*"
# 重新定义 express 库的类型
import { Router, Request, Response } from 'express'
// express 库的类型定义文件 .d.ts 文件类型描述不准确
interface RequestWithBody extends Request {
body: {
// 属性值是字符串
[key: string]: string | undefined
}
}
// 使用
router.post('/getData', (req: RequestWithBody, res: Response) => {
const { password } = req.body
if (password === '123') {
const secret = 'secretKey'
const url = `http://www.dell-lee.com/typescript/demo.html?secret=${secret}`
const analyze = DellAnalyze.getInstance()
new Crowller(url, analyze)
res.send('getData Success')
} else {
res.send('password error!')
}
})
# 对类型定义文件进行扩展
比如我们自定义中间件,想要在 request 中的内容:
// 自定义中间件
app.use((req: Request, res: Response, next: NextFunction) => {
// req 没有 teacherName 这个属性,会报错
// ts 进行了类型融合,将原来的 express 的类型描述文件跟我们自定的进行融合
req.teacherName = 'jie'
next()
})
会进行报错,上面的写法,我们可以再定义一个类似的类型描述文件,让 ts 进行融合 新建 custom.d.ts 文件:
declare namespace Express {
interface Request {
teacherName: string
}
}
# 使用 cookie-session 插件
我们可以使用 cookie-session 插件来完善登录功能,首先进行安装:npm install cookie-session --save 然后进行使用:
import cookieSession from 'cookie-session'
app.use(
cookieSession({
name: 'session',
keys: ['teacher-jie'],
maxAge: 24 * 60 * 60 * 1000,
})
)
// 然后在路由中可以直接设置 session
router.post('/login', (req: BodyRequest, res: Response) => {
const { password } = req.body
const isLogin = req.session ? req.session.login : undefined
if (isLogin) {
res.send('已经登录过')
} else {
if (password === '123' && req.session) {
req.session.login = true
res.send('登录成功')
} else {
res.send('登录失败')
}
}
})
# ts 其他
定义一个接口,有一个可有可无的属性:
interface Result {
success: boolean
// 可有可无的属性
errMag?: string
}
定义一个接口,属性值是字符串:
interface BodyRequest extends Request {
body: {
[key: string]: string | undefined
}
}
# statics、protected 方法
静态方法,是通过类直接去调用。实例不能调用;protected 方法或者属性是在类以及他的子类中内部中可以使用,实例以及外部不能使用。