# 初始化项目

首先 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 插件来完善登录功能,首先进行安装: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 方法或者属性是在类以及他的子类中内部中可以使用,实例以及外部不能使用。

评 论:

更新: 11/21/2020, 7:00:56 PM