飞道的博客

TS入门

660人阅读  评论(0)

目录

一、快速上手

二、vue的TS

三、使用vue-class-component

四、vue-property-decorator

五、TypeScript 不适合在 vue 业务开发中使用吗?

六、Property 'name' has no initializer

七、下载量对比

八、tsconfig.json

九、shims-vue.d.ts

十、shims-tsx.d.ts

十一、vuex-class

十二、ts

十三、装饰器(Decorator)

十四、红绿灯

十五、Property '$router' does not exist on type 'Login'

十六、使用createDecorator自定义装饰器

十七、TSLint去掉分号和逗号的检查

十八、react与TS

十九、图片转base64

二十、React+TS

参考链接:


 

 

 

 

一、快速上手

TypeScriptJavaScript 的强类型版本。然后在编译期去掉类型和特有语法,生成纯粹的 JavaScript 代码。

TypeScriptJavaScript 的超集,这意味着他支持所有的 JavaScript 语法。

强类型语言的优势在于静态类型检查。

TypeScript是微软开发的语言。

vue3.0使用ts开发。

是github开源项目:https://github.com/Microsoft/TypeScript

2012 年 10 月诞生。

vscode是用ts编写的:https://github.com/Microsoft/vscode/

装包:

yarn global add typescript

检查版本:

 tsc -V

初始化:

tsc --init

 

index.ts:


  
  1. function greeter(person) {
  2. return "Hello, " + person;
  3. }
  4. let user = "Jane User";
  5. document.body.innerHTML = greeter(user);

编程成js文件:

tsc index.ts

index.js:


  
  1. function greeter(person) {
  2. return "Hello, " + person;
  3. }
  4. var user = "Jane User";
  5. document.body.innerHTML = greeter(user);

类型检查:

如果函数参数声明是字符串,却传了数字,会有警告信息


  
  1. function greeter(person:string) {
  2. return "Hello, " + person;
  3. }
  4. let user = 1;
  5. document.body.innerHTML = greeter(user);

及时不传参数也会报错:

interface接口:

定义Person包含的字段


  
  1. interface Person {
  2. firstName: string;
  3. lastName: string;
  4. }
  5. function greeter(person: Person) {
  6. return "Hello, " + person.firstName + " " + person.lastName;
  7. }
  8. let user = { firstName: "Jane", lastName: "User" };
  9. document.body.innerHTML = greeter(user);

使用class创建类:


  
  1. class Student {
  2. fullName: string;
  3. constructor(public firstName, public middleInitial, public lastName) {
  4. this.fullName = firstName + " " + middleInitial + " " + lastName;
  5. }
  6. }
  7. interface Person {
  8. firstName: string;
  9. lastName: string;
  10. }
  11. function greeter(person : Person) {
  12. return "Hello, " + person.firstName + " " + person.lastName;
  13. }
  14. let user = new Student( "Jane", "M.", "User");
  15. document.body.innerHTML = greeter(user);

编译后是:


  
  1. var Student = /** @class */ ( function () {
  2. function Student(firstName, middleInitial, lastName) {
  3. this.firstName = firstName;
  4. this.middleInitial = middleInitial;
  5. this.lastName = lastName;
  6. this.fullName = firstName + " " + middleInitial + " " + lastName;
  7. }
  8. return Student;
  9. }());
  10. function greeter(person) {
  11. return "Hello, " + person.firstName + " " + person.lastName;
  12. }
  13. var user = new Student( "Jane", "M.", "User");
  14. document.body.innerHTML = greeter(user);

访问网页,index.html:


  
  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  6. <title>Document </title>
  7. </head>
  8. <body>
  9. <script src="./index.js"> </script>
  10. </body>
  11. </html>

效果:

自动补全功能:

二、vue的TS

引入Vue文件的时候需要加上.vue后缀,否则编辑器识别不到

TS路由:


  
  1. import Vue from 'vue'
  2. import VueRouter, { RouteConfig } from 'vue-router'
  3. import Home from '../views/Home.vue'
  4. Vue.use(VueRouter)
  5. const routes: Array<RouteConfig> = [
  6. {
  7. path: '/',
  8. name: 'Home',
  9. component: Home
  10. },
  11. {
  12. path: '/about',
  13. name: 'About',
  14. // route level code-splitting
  15. // this generates a separate chunk (about.[hash].js) for this route
  16. // which is lazy-loaded when the route is visited.
  17. component: () => import( /* webpackChunkName: "about" */ '../views/About.vue')
  18. }
  19. ]
  20. const router = new VueRouter({
  21. mode: 'history',
  22. base: process.env.BASE_URL,
  23. routes
  24. })
  25. export default router

  
  1. import Vue from 'vue'
  2. import VueRouter, { RouteConfig } from 'vue-router'
  3. Vue.use(VueRouter)
  4. const routes: Array<RouteConfig> = [
  5. {
  6. path: '/',
  7. redirect: '/login'
  8. },
  9. {
  10. path: '/login',
  11. component: () => import( '../views/Login.vue')
  12. }
  13. ]
  14. const router = new VueRouter({
  15. mode: 'history',
  16. base: process.env.BASE_URL,
  17. routes
  18. })
  19. export default router

三、使用vue-class-component

https://class-component.vuejs.org/

annotating:注释

加加减减:


  
  1. <template>
  2. <div>
  3. <div>{{count}} </div>
  4. <button @click="handleSub"></button>
  5. <button @click="handleAdd"></button>
  6. </div>
  7. < /template>
  8. <script>
  9. import Vue from 'vue'
  10. import Component from 'vue-class-component'
  11. @Component
  12. class Login extends Vue {
  13. count = 0
  14. handleSub() {
  15. this.count--
  16. }
  17. handleAdd() {
  18. this.count++
  19. }
  20. }
  21. export default Login
  22. </script>

或者:


  
  1. <template>
  2. <div>
  3. <div>{{count}} </div>
  4. <button @click="handleSub"></button>
  5. <button @click="handleAdd"></button>
  6. </div>
  7. < /template>
  8. <script>
  9. import Vue from 'vue'
  10. import Component from 'vue-class-component'
  11. @Component
  12. class Login extends Vue {
  13. data() {
  14. return {
  15. count: 0
  16. }
  17. }
  18. handleSub() {
  19. this.count--
  20. }
  21. handleAdd() {
  22. this.count++
  23. }
  24. }
  25. export default Login
  26. </script>

 

v-model:


  
  1. <template>
  2. <div>
  3. <input v-model="username">
  4. </div>
  5. </template>
  6. <script>
  7. import Vue from 'vue'
  8. import Component from 'vue-class-component'
  9. @Component
  10. class Login extends Vue {
  11. username = 'admin'
  12. }
  13. export default Login
  14. < /script>

挂载完声明周期:


  
  1. <template>
  2. <div>
  3. 1
  4. </div>
  5. < /template>
  6. <script>
  7. import Vue from 'vue'
  8. import Component from 'vue-class-component'
  9. @Component
  10. class Login extends Vue {
  11. mounted () {
  12. console.log('挂载完')
  13. }
  14. }
  15. export default Login
  16. </script>

计算属性:


  
  1. <template>
  2. <div>
  3. {{double}}
  4. </div>
  5. < /template>
  6. <script>
  7. import Vue from 'vue'
  8. import Component from 'vue-class-component'
  9. @Component
  10. class Login extends Vue {
  11. count = 1
  12. get double() {
  13. return this.count * 2
  14. }
  15. }
  16. export default Login
  17. </script>

父子组件传值:

父组件


  
  1. <template>
  2. <div>
  3. <Icon :name="visible ? 'xianshimima' : 'buxianshimima'" @onClick="handleVisible"> </Icon>
  4. </div>
  5. < /template>
  6. <script>
  7. import Vue from 'vue'
  8. import Component from 'vue-class-component'
  9. import Icon from '../components/Icon '
  10. @Component({
  11. components: {
  12. Icon
  13. }
  14. })
  15. class Login extends Vue {
  16. visible = false
  17. handleVisible() {
  18. this.visible = !this.visible
  19. }
  20. }
  21. export default Login
  22. </script>

子组件


  
  1. <template>
  2. <span :class="[`icon iconfont icon-${name}`]" @click="handleClick"></span>
  3. < /template>
  4. <script lang="ts">
  5. import Vue from 'vue'
  6. import { Component, Prop } from 'vue-property-decorator'
  7. @Component
  8. class Icon extends Vue {
  9. @Prop()
  10. name: string
  11. handleClick() {
  12. this.$emit('onClick')
  13. }
  14. }
  15. export default Icon
  16. </script>

子组件也可以写成这种


  
  1. <template>
  2. <span :class="[`icon iconfont icon-${name}`]" @click="handleClick"></span>
  3. < /template>
  4. <script lang="ts">
  5. import Vue from 'vue'
  6. import Component from 'vue-class-component'
  7. const IconProps = Vue.extend({
  8. props: {
  9. name: String
  10. }
  11. })
  12. @Component
  13. class Icon extends IconProps {
  14. handleClick() {
  15. this.$emit('onClick')
  16. }
  17. }
  18. export default Icon
  19. </script>

增加路由hook:

vue-class-component.ts


  
  1. import Component from 'vue-class-component'
  2. Component.registerHooks([
  3. "beforeRouteEnter"
  4. ])

在入口文件main.ts里引入这个文件

在组件里可以使用


  
  1. <script>
  2. import Vue from 'vue'
  3. import Component from 'vue-class-component'
  4. @Component
  5. export default class Test2 extends Vue {
  6. beforeRouteEnter(to, from, next) {
  7. console.log( 1)
  8. next()
  9. }
  10. }
  11. < /script>

 

 

四、vue-property-decorator

https://www.npmjs.com/package/vue-property-decorator

vue属性装饰器

父子组件传值,传参

父组件:


  
  1. <template>
  2. <div>
  3. <Icon :name="visible ? 'show' : 'hide'" @onClick="handleVisible"> </Icon>
  4. </div>
  5. < /template>
  6. <script lang="ts">
  7. import { Vue, Component } from 'vue-property-decorator'
  8. import Icon from '../components/Icon.vue '
  9. @Component({
  10. components: {
  11. Icon
  12. }
  13. })
  14. class Login extends Vue {
  15. visible = false
  16. handleVisible(payload:object) {
  17. this.visible = !this.visible
  18. }
  19. }
  20. export default Login
  21. </script>

子组件:


  
  1. <template>
  2. <span :class="[`icon iconfont icon-${name}`]" @click="handleClick"></span>
  3. < /template>
  4. <script lang="ts">
  5. import { Vue, Component, Prop, Emit } from 'vue-property-decorator'
  6. @Component
  7. class Icon extends Vue {
  8. @Prop({ default: 'zhanwei' })
  9. name: string
  10. @Emit('onClick')
  11. handleClick() {
  12. return { id: 2 }
  13. }
  14. }
  15. export default Icon
  16. </script>

五、TypeScript 不适合在 vue 业务开发中使用吗?

https://www.zhihu.com/question/310485097/answer/591869966

 

六、Property 'name' has no initializer

Property 'name' has no initializer and is not definitely assigned in the constructor.

解决办法一:

把tsconfig.json文件里的strict字段改成false

解决办法二:

在属性名后面加叹号,这是一种修饰符,标识忽略


  
  1. <template>
  2. <span :class="[`icon iconfont icon-${name}`]" @click="handleClick"></span>
  3. < /template>
  4. <script lang="ts">
  5. import { Vue, Component, Prop, Emit } from 'vue-property-decorator'
  6. @Component
  7. class Icon extends Vue {
  8. @Prop({ default: 'zhanwei' })
  9. name!: string
  10. @Emit('onClick')
  11. handleClick() {
  12. return { id: 2 }
  13. }
  14. }
  15. export default Icon
  16. </script>

七、下载量对比

 

八、tsconfig.json

ts的配置


  
  1. {
  2. "compilerOptions": {
  3. "target": "esnext", //编译的目标版本
  4. "module": "esnext", //指定生成哪个模块系统代码
  5. "strict": true, //静态类型检查
  6. "jsx": "preserve", //
  7. "importHelpers": true,
  8. "moduleResolution": "node",
  9. "experimentalDecorators": true,
  10. "esModuleInterop": true,
  11. "allowSyntheticDefaultImports": true,
  12. "sourceMap": true, // 是否生成map文件
  13. "baseUrl": ".",
  14. "types": [
  15. "webpack-env"
  16. ],
  17. "paths": {
  18. "@/*": [
  19. "src/*"
  20. ]
  21. },
  22. "lib": [
  23. "esnext",
  24. "dom",
  25. "dom.iterable",
  26. "scripthost"
  27. ]
  28. },
  29. "include": [
  30. "src/**/*.ts",
  31. "src/**/*.tsx",
  32. "src/**/*.vue",
  33. "tests/**/*.ts",
  34. "tests/**/*.tsx"
  35. ],
  36. "exclude": [
  37. "node_modules"
  38. ]
  39. }

 

九、shims-vue.d.ts

shims: 垫片

由于 TypeScript 默认并不支持 *.vue 后缀的文件,所以在 vue 项目中引入的时候需要创建一个shims-vue.d.ts 文件,放在项目应使用目录下,例如 src/shims-vue.d.ts,用来支持*.vue 后缀的文件;

主要用于 TypeScript 识别.vue 文件,Ts默认并不支持导入 vue 文件,这个文件告诉ts 导入.vue 文件都按VueConstructor<Vue>处理

 


  
  1. declare module '*.vue' {
  2. import Vue from 'vue'
  3. export default Vue
  4. }

十、shims-tsx.d.ts

允许你以.tsx结尾的文件,在Vue项目中编写jsx代码


  
  1. import Vue, { VNode } from 'vue'
  2. declare global {
  3. namespace JSX {
  4. // tslint:disable no-empty-interface
  5. interface Element extends VNode {}
  6. // tslint:disable no-empty-interface
  7. interface ElementClass extends Vue {}
  8. interface IntrinsicElements {
  9. [elem: string]: any;
  10. }
  11. }
  12. }

十一、vuex-class

https://www.npmjs.com/package/vuex-class

使用仓库做加加减减

仓库:


  
  1. import Vue from 'vue'
  2. import Vuex from 'vuex'
  3. Vue.use(Vuex)
  4. interface Payload {
  5. key: string,
  6. value: any
  7. }
  8. export default new Vuex.Store({
  9. state: {
  10. count: 0
  11. },
  12. mutations: {
  13. setState(state:any, payload:Payload) {
  14. state[payload.key] = payload.value
  15. }
  16. },
  17. actions: {
  18. },
  19. modules: {
  20. }
  21. })

页面:


  
  1. <template>
  2. <div>
  3. <div>{{count}} </div>
  4. <button @click="handleSub"></button>
  5. <button @click="handleAdd"></button>
  6. </div>
  7. < /template>
  8. <script lang="ts">
  9. import Vue from 'vue'
  10. import Component from 'vue-class-component'
  11. import { State, Mutation } from 'vuex-class'
  12. @Component
  13. class Login extends Vue {
  14. @State('count') count!:number
  15. @Mutation('setState') setState!:Function
  16. handleSub() {
  17. let count = this.count - 1
  18. this.setState({ key: 'count', value: count })
  19. }
  20. handleAdd() {
  21. let count = this.count + 1
  22. this.setState({ key: 'count', value: count })
  23. }
  24. }
  25. export default Login
  26. </script>

 

十二、ts

初始化:

在空文件夹里打开终端  -> 输入tsc --init  自动生成tsconfig.json


  
  1. {
  2. "compilerOptions": {
  3. /* Basic Options */
  4. // "incremental": true, /* Enable incremental compilation */
  5. "target": "es5", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', or 'ESNEXT'. */
  6. "module": "commonjs", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */
  7. // "lib": [], /* Specify library files to be included in the compilation. */
  8. "allowJs": true, /* Allow javascript files to be compiled. */
  9. // "checkJs": true, /* Report errors in .js files. */
  10. // "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */
  11. // "declaration": true, /* Generates corresponding '.d.ts' file. */
  12. // "declarationMap": true, /* Generates a sourcemap for each corresponding '.d.ts' file. */
  13. // "sourceMap": true, /* Generates corresponding '.map' file. */
  14. // "outFile": "./", /* Concatenate and emit output to single file. */
  15. "outDir": "./js", //输出文件夹 /* Redirect output structure to the directory. */
  16. // "rootDir": "./", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */
  17. // "composite": true, /* Enable project compilation */
  18. // "tsBuildInfoFile": "./", /* Specify file to store incremental compilation information */
  19. // "removeComments": true, /* Do not emit comments to output. */
  20. // "noEmit": true, /* Do not emit outputs. */
  21. // "importHelpers": true, /* Import emit helpers from 'tslib'. */
  22. // "downlevelIteration": true, /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */
  23. // "isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */
  24. /* Strict Type-Checking Options */
  25. "strict": true, /* Enable all strict type-checking options. */
  26. // "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */
  27. // "strictNullChecks": true, /* Enable strict null checks. */
  28. // "strictFunctionTypes": true, /* Enable strict checking of function types. */
  29. // "strictBindCallApply": true, /* Enable strict 'bind', 'call', and 'apply' methods on functions. */
  30. // "strictPropertyInitialization": true, /* Enable strict checking of property initialization in classes. */
  31. // "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */
  32. // "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */
  33. /* Additional Checks */
  34. // "noUnusedLocals": true, /* Report errors on unused locals. */
  35. // "noUnusedParameters": true, /* Report errors on unused parameters. */
  36. // "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */
  37. // "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */
  38. /* Module Resolution Options */
  39. // "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */
  40. // "baseUrl": "./", /* Base directory to resolve non-absolute module names. */
  41. // "paths": {}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */
  42. // "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */
  43. // "typeRoots": [], /* List of folders to include type definitions from. */
  44. // "types": [], /* Type declaration files to be included in compilation. */
  45. // "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */
  46. "esModuleInterop": true, /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */
  47. // "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */
  48. // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */
  49. /* Source Map Options */
  50. // "sourceRoot": "", /* Specify the location where debugger should locate TypeScript files instead of source locations. */
  51. // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */
  52. // "inlineSourceMap": true, /* Emit a single file with source maps instead of having a separate file. */
  53. // "inlineSources": true, /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */
  54. /* Experimental Options */
  55. "experimentalDecorators": true, //装饰器 /* Enables experimental support for ES7 decorators. */
  56. // "emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */
  57. /* Advanced Options */
  58. "forceConsistentCasingInFileNames": true /* Disallow inconsistently-cased references to the same file. */
  59. }
  60. }

监视ts文件变化,自动编译:

vscode -> 终端 -> 运行任务 -> typescript -> tsc: 监视 - (tsconfig.json的目录)

 

课堂练习(1):


  
  1. function test(name:string) {
  2. console.log(name)
  3. }
  4. test( 'hello3')
  5. //元组
  6. let tuple:[string, number, string] = [ 'a', 1, 'b']
  7. console.log(tuple)
  8. //任意值
  9. let person:any = 'xu'
  10. console.log(person)
  11. //四要素:调用, 参数,返回值,作用
  12. function fun(name:string):string {
  13. console.log(name)
  14. return name
  15. }
  16. fun( 'xu')
  17. //never 不可到达
  18. const error = (): never => {
  19. throw new Error( '错误')
  20. }
  21. //error()
  22. const loop = () => {
  23. while( true);
  24. }
  25. //loop()
  26. console.log( 1)
  27. //枚举
  28. enum Color { Red = 2, Green, Blue }
  29. console.log(Color.Red) //2
  30. enum obj {
  31. None,
  32. Read,
  33. G = '123'.length
  34. }
  35. console.log(obj)
  36. enum Enum {
  37. A
  38. }
  39. let a = Enum.A
  40. console.log(a) //0
  41. let na = Enum[a]
  42. console.log(na) //A

课堂练习(2):


  
  1. function sayHello(person: string) {
  2. return 'Hello,' + person
  3. }
  4. let user:string = 'a'
  5. console.log(sayHello(user))
  6. let num:number = 1
  7. //没有显示声明类型,则会进行类型推断
  8. let a = 'a'
  9. a = 'b' //赋值其他类型,则会报错
  10. let flag:boolean = true
  11. //数字类型的数组
  12. let arr:number[] = [ 1, 2]
  13. let strArr:string[] = [ 'a', 'b']
  14. let objArr:object[] = [{}]
  15. //泛型方式
  16. let arr1: Array<number> = [ 1]
  17. let strArr1: Array<string> = [ 'a', 'b']
  18. //元组
  19. let arr2:[number, string, boolean] = [ 1, '2', true]
  20. //null, undefined
  21. let my_null: null = null
  22. let my_undefined: undefined = undefined
  23. //可以是字符串也可以是undefined
  24. let c:string | undefined
  25. console.log(c)
  26. //never 从来不会出现的值
  27. // let my_never: never = (() => {
  28. // throw new Error()
  29. // })()
  30. //any 任何类型
  31. let my_any:any = '任何类型'
  32. console.log(my_any)
  33. //任何类型的数组
  34. let arrAny:any[] = [ 'a', 1, true]
  35. function run():void {
  36. console.log( 'run')
  37. }
  38. run()
  39. function getName():string {
  40. return 'xu'
  41. }
  42. console.log(getName())
  43. const myRun = (): void => {
  44. console.log( 'myRun')
  45. }
  46. myRun()
  47. const myGetName = (): string => {
  48. return 'myGetName'
  49. }
  50. console.log(myGetName())
  51. //构造函数Boolean 创造的不是布尔值
  52. //let myBoolean:boolean = new Boolean(1)

课堂练习(3):


  
  1. //函数
  2. //没有返回值是用void
  3. function getInfo(name:string, age:number):string {
  4. return `我叫${name},今年${age}岁。`
  5. }
  6. console.log(getInfo( 'xu', 30))
  7. let getInfo1 = (name:string, age:number): string => {
  8. return `我叫${name},今年${age}岁。`
  9. }
  10. console.log(getInfo( 'xu', 31))
  11. //完整类型
  12. let getInfo2: (name:string, age:number) => string = (name:string, age:number): string => {
  13. return `我叫${name},今年${age}岁。`
  14. }
  15. let getInfo3: Function = (name:string, age:number): string => {
  16. return `我叫${name},今年${age}岁。`
  17. }
  18. //函数可选参数,加个问好
  19. function myInfo(name: string, age?: number):string {
  20. if ( typeof age === 'number') {
  21. return `我叫${name},今年${age}岁。`
  22. } else {
  23. return `我叫${name}`
  24. }
  25. }
  26. console.log(myInfo( 'xu'))
  27. //默认值
  28. function myInfo1(name: string, age:number = 32):string {
  29. if ( typeof age === 'number') {
  30. return `我叫${name},今年${age}岁。`
  31. } else {
  32. return `我加${name}`
  33. }
  34. }
  35. console.log(myInfo1( 'xu'))
  36. //求和
  37. function sum(a:number, b:number):number {
  38. return a + b
  39. }
  40. console.log(sum( 1, 2))
  41. //剩余参数
  42. function sum1(...rest:number[]):number {
  43. console.log(rest) //数组
  44. return rest.reduce( (prev, item) => {
  45. return prev + item
  46. }, 0)
  47. }
  48. console.log(sum1( 1, 2, 3, 4, 5))
  49. //枚举类型
  50. // 0: 女, 1:男, 2:保密
  51. enum Sex {
  52. gril,
  53. boy,
  54. secret
  55. }
  56. let xu:Sex = Sex.boy
  57. console.log(xu)
  58. let xu1:Sex = 3
  59. console.log(xu1)
  60. function getSex(sex:Sex):string {
  61. if (sex === Sex.gril) {
  62. return '我是女孩'
  63. } else if (sex === Sex.boy) {
  64. return '我是男孩'
  65. } else {
  66. return '保密'
  67. }
  68. }
  69. console.log(getSex(xu))
  70. class A {
  71. v:number = 100
  72. test(num:number) {
  73. if (num > this.v) {
  74. console.log( '大了');
  75. } else if (num < this.v) {
  76. console.log( '小了')
  77. } else {
  78. console.log( '对了')
  79. }
  80. }
  81. }
  82. let a = new A()
  83. a.test( 100)
  84. let isDone:boolean = false
  85. let isDone1:object = new Boolean( 1)
  86. let isDone2: Boolean = new Boolean( 1)
  87. let isDone3:boolean = Boolean( 1)
  88. //变量如果在声明的时候,未指定其类型,那么它会被识别为任意值类型
  89. let something //let something:any
  90. something = 1
  91. something = 'a'
  92. //联合类型
  93. let myA: string | number
  94. myA = 'a'
  95. myA = 1
  96. function getLength(something: string | []):number {
  97. return something.length
  98. }
  99. let myB: string | number
  100. myB = 'A'
  101. myB.length
  102. myB = 1
  103. //myB.length //报错
  104. let arr:number[] = [ 1, 3, 2]
  105. arr.sort( (a, b) => {
  106. return a - b
  107. })
  108. console.log(arr)
  109. function is(ar:string,sr:string):boolean {
  110. let result = true
  111. if(ar.length===sr.length){
  112. for( let i= 0;i<ar.length;i++){
  113. if(ar.indexOf(sr[i])=== -1){
  114. result = false
  115. }
  116. }
  117. result = true
  118. } else {
  119. result = false
  120. }
  121. return result
  122. }
  123. console.log(is( "asa", "aas") )
  124. function isAng(arr:string,trr:string):boolean{
  125. if(arr.length===trr.length){
  126. for( var i= 0;i<arr.length;i++){
  127. if(arr.indexOf(trr[i])=== -1){
  128. return false
  129. }
  130. }
  131. return true
  132. }
  133. return false
  134. }
  135. console.log(isAng( 'listen', 'silenta'))

课堂练习(4):


  
  1. //函数重载
  2. function add(a:string, b:string):string;
  3. function add( a:number, b:number): number;
  4. function add( a:any, b:any): any {
  5. if ( typeof a === 'string') {
  6. return a + '---' + b
  7. } else {
  8. return a + b
  9. }
  10. }
  11. console.log(add( 'a', 'b'))
  12. //类
  13. //修饰符 pubulic protected private
  14. //静态属性 static
  15. class Person {
  16. public name: string
  17. protected age: number
  18. static height: number = 170
  19. constructor(name:string, age:number) {
  20. this.name = name
  21. this.age = age
  22. console.log(Person.height, Person.getHeight())
  23. }
  24. protected getName():string {
  25. return `我的名字叫${this.name}`
  26. }
  27. static getHeight():number {
  28. return this.height
  29. }
  30. }
  31. let xu = new Person( 'xu', 30)
  32. //console.log(xu.getName())
  33. console.log(Person.getHeight())
  34. // class Animal {
  35. // name:string
  36. // constructor(name:string) {
  37. // this.name = name
  38. // }
  39. // sayHi() {
  40. // return `My name is ${this.name}`
  41. // }
  42. // }
  43. // let a = new Animal('jack')
  44. // console.log(a.sayHi())
  45. //继承
  46. class Programmer extends Person {
  47. job:string
  48. constructor(name:string, age:number, job:string) {
  49. super(name, age)
  50. this.job = job
  51. console.log( this.age)
  52. }
  53. getJob() {
  54. return `${this.getName()},年龄${this.age},我的工作是${this.job}`
  55. }
  56. }
  57. let xu1 = new Programmer( '徐同保', 30, 'web前端')
  58. //console.log(xu1.getName())
  59. console.log(xu1.getJob())
  60. //console.log(xu1.age)
  61. //抽象类
  62. abstract class Animal {
  63. name: string
  64. constructor(name: string) {
  65. this.name = name
  66. }
  67. getName():string {
  68. return this.name
  69. }
  70. abstract eat(): void
  71. }
  72. class Cat extends Animal {
  73. food: string
  74. constructor(name: string, food: string) {
  75. super(name)
  76. this.food = food
  77. }
  78. eat(): void {
  79. console.log( `${this.getName()}爱吃鱼`)
  80. }
  81. }
  82. let ketty = new Cat( '小猫', '鱼')
  83. ketty.eat()
  84. //更简练的写法,不用定义name了,也不需要赋值
  85. class MyAnimal {
  86. constructor(public name:string) {
  87. }
  88. getName() {
  89. return this.name
  90. }
  91. }
  92. let myAnimal = new MyAnimal( '小猫')
  93. console.log(myAnimal.getName())
  94. //接口
  95. interface Goods {
  96. name: string
  97. price: number
  98. flag: boolean
  99. }
  100. let cartList: Goods[] = [
  101. {
  102. name: '苹果',
  103. price: 8,
  104. flag: true
  105. },
  106. {
  107. name: '香蕉',
  108. price: 5,
  109. flag: false
  110. }
  111. ]
  112. function goodsInfo(goods:Goods) {
  113. console.log( `${goods.name}现在${goods.price}元一斤${goods.flag ? ',正在促销' : ''}`)
  114. }
  115. cartList.forEach( item => {
  116. goodsInfo(item)
  117. })
  118. //函数接口
  119. interface GoodsInfo {
  120. (goods: Goods): string
  121. }
  122. let myGoodsInfo: GoodsInfo = (goods:Goods): string => {
  123. return `${goods.name}现在${goods.price}元一斤${goods.flag ? ',正在促销' : ''}`
  124. }
  125. //类接口,实现接口的时候使用implements(实现)
  126. interface PersonI {
  127. name: string,
  128. age: number,
  129. getName():string
  130. }
  131. interface WebI {
  132. name: string,
  133. age: number,
  134. job: string
  135. getName(): string
  136. getJob(): string
  137. }
  138. //接口也可以继承
  139. interface WebIPlus extends PersonI {
  140. job: string,
  141. getJob(): string
  142. }
  143. class MyPerson implements PersonI {
  144. name: string
  145. age: number
  146. constructor(name:string, age:number) {
  147. this.name = name
  148. this.age = age
  149. }
  150. getName() {
  151. return this.name
  152. }
  153. }
  154. class Web extends MyPerson implements WebIPlus {
  155. job: string
  156. constructor(name: string, age: number, job: string) {
  157. super(name, age)
  158. this.job = job
  159. }
  160. getJob() {
  161. return this.job
  162. }
  163. getInfo() {
  164. return `${this.name},${this.age},${this.job}`
  165. }
  166. }
  167. let xu2 = new Web( 'xu', 30, 'web')
  168. console.log(xu2.getInfo())

课堂练习(5):


  
  1. let arr: Array<string> = [ 'a', 'b', 'c']
  2. //泛型函数
  3. function getMin<T>(arr:T[]):T {
  4. let min:T = arr[ 0]
  5. arr.forEach( val => {
  6. if (val < min) {
  7. min = val
  8. }
  9. })
  10. return min
  11. }
  12. let min = getMin<number>([ 5, 2, 8, 4, 4])
  13. console.log(min)
  14. let min1 = getMin<string>([ 'd', 's', 'c', 'e', 'f'])
  15. console.log(min1)
  16. //泛型类
  17. class Min<T> {
  18. list: T[] = []
  19. add(params: T): void {
  20. this.list.push(params)
  21. }
  22. getMin(): T {
  23. let min:T = this.list[ 0]
  24. this.list.forEach( val => {
  25. if (val < min) {
  26. min = val
  27. }
  28. })
  29. return min
  30. }
  31. }
  32. //函数接口泛型
  33. interface Min<T> {
  34. (arr: T[]): T
  35. }
  36. //装饰器
  37. function logClass(target:any) {
  38. console.log( '我是装饰器', target)
  39. target.prototype.name = '我是装饰器添加的name'
  40. target.prototype.getName = function () {
  41. console.log( '我是装饰器添加的方法')
  42. }
  43. }
  44. function logName(params:any) {
  45. console.log(params)
  46. return function(target:any, attr:any) {
  47. console.log( '属性装饰器', target) //实例
  48. console.log( 'attr', attr) //使用装饰器的属性
  49. target[attr] = params
  50. }
  51. }
  52. // function logName(target:any, attr:any) {
  53. // console.log('属性装饰器', target) //实例
  54. // console.log('attr', attr) //使用装饰器的属性
  55. // target[attr] = 'xu'
  56. // }
  57. @logClass
  58. class Person {
  59. @logName( '我是Person类')
  60. myName: string | undefined
  61. @logName( 40)
  62. age:number | undefined
  63. getInfo() {
  64. console.log( this.myName, this.age)
  65. }
  66. }
  67. let a = new Person()
  68. console.log(a)
  69. a.getInfo()

 

笔记:

TypeScript 中,使用 : 指定变量的类型,: 的前后有没有空格都可以。

TypeScript 只会进行静态检查,如果发现有错误,编译的时候就会报错。

构造函数 Boolean 创造的对象不是布尔值。

当构造函数修饰为 private 时,该类不允许被继承或者实例化。

当构造函数修饰为 protected 时,该类只允许被继承,不允许实例化。

只读属性关键字,只允许出现在属性声明或索引签名或构造函数中。

一个类只能继承自另一个类,但是可以实现多个接口。

变量如果在声明的时候,未指定其类型,那么它会被识别为任意值类型。

联合类型使用 | 分隔每个类型。

泛型(Generics)是指在定义函数、接口或类的时候,不预先指定具体的类型,而在使用的时候再指定类型的一种特性。

十三、装饰器(Decorator)

装饰器是一个对类进行处理的函数。装饰器函数的第一个参数,就是所要装饰的目标类。


  
  1. @decorator
  2. class A {}
  3. // 等同于
  4. class A {}
  5. A = decorator(A) || A;

如果觉得一个参数不够用,可以在装饰器外面再封装一层函数。


  
  1. function testable(isTestable) {
  2. return function(target) {
  3. target.isTestable = isTestable;
  4. }
  5. }

mixins实例:


  
  1. //装饰器函数,list合并到原型链上
  2. const mixins = (...list:any) => (target:any) => {
  3. Object.assign(target.prototype, ...list)
  4. }
  5. //待合并的对象
  6. const Foo = {
  7. name: 'xu',
  8. foo() {
  9. console.log( 'foo')
  10. },
  11. bar() {
  12. console.log( 'bar')
  13. }
  14. }
  15. //使用装饰器
  16. @mixins(Foo)
  17. class MyClass {
  18. }
  19. //测试
  20. let obj = new MyClass();
  21. (obj as any).foo();
  22. (obj as any).bar();
  23. console.log((obj as any).name)

装饰器有注释的作用。

由于存在函数提升,使得装饰器不能用于函数。

日志实例:


  
  1. //计算器类
  2. class Computed {
  3. name:string
  4. constructor(name:string) {
  5. this.name = name
  6. }
  7. @log
  8. add(a:number, b:number) {
  9. console.log( this.name)
  10. return a + b
  11. }
  12. @log
  13. sub(a:number, b:number) {
  14. return a - b
  15. }
  16. }
  17. //日志装饰器
  18. function log(target:any, name:any, descriptor:any) {
  19. let oldValue = descriptor.value
  20. descriptor.value = function () {
  21. //日志
  22. console.log( `日志:调用${name},参数是${Array.from(arguments)}`)
  23. //return oldValue.call(this, ...arguments) //执行老方法
  24. return oldValue.apply( this, arguments)
  25. }
  26. return descriptor
  27. }
  28. //测试
  29. const computed = new Computed( 'xu')
  30. console.log(computed.add( 2, 4))
  31. console.log(computed.sub( 4, 2))

十四、红绿灯


  
  1. class Light {
  2. constructor() {
  3. this.init()
  4. }
  5. init() {
  6. return this.light( 3, '绿灯')
  7. .then( () => {
  8. return this.light( 2, '红灯')
  9. })
  10. .then( () => {
  11. return this.light( 1, '黄灯')
  12. }).then( () => {
  13. this.init()
  14. }).catch( () => {
  15. console.log( '失败了')
  16. })
  17. }
  18. light(time: number, type: string) {
  19. return new Promise( (resolve, reject) => {
  20. let timer = setInterval( () => {
  21. console.log(type, time)
  22. time--
  23. if (time === 0) {
  24. clearInterval(timer)
  25. resolve()
  26. //reject()
  27. }
  28. }, 1000)
  29. })
  30. }
  31. }
  32. let ligth = new Light()

 


  
  1. interface LampI {
  2. loop: number
  3. start(): void
  4. }
  5. //红绿灯
  6. class Lamp<T> {
  7. loop: number
  8. constructor(public green: number, public red: number, public yellow: number) {
  9. this.loop = 0
  10. }
  11. start() {
  12. let loopFun = async () => {
  13. await new Promise( (resolve) => {
  14. setTimeout( () => {
  15. this.loop++
  16. this.print()
  17. loopFun()
  18. }, 1000)
  19. })
  20. }
  21. loopFun()
  22. }
  23. test(a:T) {
  24. console.log(a)
  25. }
  26. private print(): void {
  27. if ( this.loop <= this.green) {
  28. console.log( `绿灯${this.green + 1 - this.loop}`)
  29. } else if ( this.loop <= this.green + this.red) {
  30. console.log( `红灯${this.green + this.red + 1 - this.loop}`)
  31. } else if ( this.loop <= this.green + this.red + this.yellow) {
  32. console.log( `黄灯${this.green + this.red + this.yellow + 1 - this.loop}`)
  33. } else {
  34. this.loop = 1
  35. console.log( `绿灯${this.green}`)
  36. }
  37. }
  38. }
  39. let lamp = new Lamp( 3, 2, 1)
  40. lamp.start()
  41. lamp.test([ 1, 2, 3])
  42. lamp.test( 'hello')

 

十五、Property '$router' does not exist on type 'Login'

解决办法:

(1)在使用路由的组件导入路由包:

import VueRouter from 'vue-router';

(2)把this断言为any

(this as any).$router.push('/index')

(3)在类里定义$router属性


  
  1. export default class Login extends Vue {
  2. $router
  3. }

十六、使用createDecorator自定义装饰器

decorators.ts:


  
  1. import { createDecorator } from 'vue-class-component'
  2. export const Log = createDecorator( (options:any, key:string) => {
  3. // 备份原始方法
  4. const originalMethod = options.methods[key]
  5. // 添加日志逻辑
  6. options.methods[key] = function wrapperMethod(...args:any) {
  7. // 打印日志
  8. console.log( `日志: ${key}(`, ...args, ')')
  9. // 执行原始方法
  10. originalMethod.apply( this, args)
  11. }
  12. })
  13. export const LogPlus = (payload: string) => createDecorator( (options:any, key:string) => {
  14. // 备份原始方法
  15. const originalMethod = options.methods[key]
  16. // 添加日志逻辑
  17. options.methods[key] = function wrapperMethod(...args:any) {
  18. // 打印日志
  19. console.log( `${payload}日志: ${key}(`, ...args, ')')
  20. // 执行原始方法
  21. originalMethod.apply( this, args)
  22. }
  23. })

使用:


  
  1. <template>
  2. <div>
  3. <div>{{msg}} </div>
  4. <div>{{count}} </div>
  5. <button @click="handleSub(1)"></button>
  6. <button @click="handleAdd(1)"></button>
  7. <TestComponent name="hello"> </TestComponent>
  8. </div>
  9. < /template>
  10. <script lang="ts">
  11. import { Vue, Component } from 'vue-property-decorator'
  12. import { Log, LogPlus } from '../utils/decorators '
  13. import TestComponent from '../components/TestComponent.vue '
  14. @Component({
  15. components: {
  16. TestComponent
  17. }
  18. })
  19. export default class Test extends Vue {
  20. msg = 'hello '
  21. count = 0
  22. @Log
  23. handleAdd(step:number) {
  24. this.count += step
  25. }
  26. @LogPlus('减法 ')
  27. handleSub(step:number) {
  28. this.count -= step
  29. }
  30. }
  31. </script>

 

十七、TSLint去掉分号和逗号的检查


  
  1. "trailing-comma": [ false],
  2. "semicolon": [ false],

十八、react与TS

脚手架:

npx create-react-app react-ts-app --typescript

按装用到的包:

yarn add react-router-dom redux react-redux redux-thunk redux-logger axios

安装TS版的声明:

yarn add @types/react-router-dom @type/react-redux

十九、图片转base64


  
  1. const getBase64Image = (url: string) => {
  2. return new Promise( (resolve,reject) => {
  3. let image = new Image();
  4. // CORS 策略,会存在跨域问题https://stackoverflow.com/questions/20424279/canvas-todataurl-securityerror
  5. image.setAttribute( "crossOrigin", 'Anonymous');
  6. image.src = url;
  7. image.onload = () => {
  8. let canvas = document.createElement( 'canvas');
  9. canvas.width = image.width;
  10. canvas.height = image.height;
  11. (canvas as any).getContext( '2d').drawImage(image, 0, 0);
  12. let result = canvas.toDataURL( 'image/png');
  13. resolve(result);
  14. }
  15. image.onerror = () => {
  16. reject( '图片流异常');
  17. };
  18. })
  19. }

 

二十、React+TS

受控组件:


  
  1. handleInput(e: ChangeEvent<HTMLInputElement>, field: string) {
  2. // @ts-ignore
  3. this.setState({
  4. [field]: e.target.value
  5. })
  6. }

HTMLInputElement:

keyUp事件:


  
  1. handleEnter(e: KeyboardEvent<HTMLInputElement>) {
  2. if(e.keyCode === 13) {
  3. this.handleLogin()
  4. }
  5. }

点击事件:


  
  1. handleVisible(e: MouseEvent<Element>, count: number) {
  2. let { visible } = this.state
  3. this.setState({
  4. visible: !visible
  5. })
  6. }

忽略类型检查:

// @ts-ignore

滚动事件:


  
  1. const handleScroll = (e: React.UIEvent<HTMLDivElement, globalThis.UIEvent>) => {
  2. let scrollTop = (e.target as Element).scrollTop
  3. console.log(scrollTop)
  4. }

withRouter:

redux数据读写:


  
  1. import React, { Dispatch } from 'react'
  2. import { connect } from 'react-redux'
  3. import { IState } from '../interface'
  4. interface IProps {
  5. list: any[],
  6. currentId: number,
  7. onSetState: (key: string, value: any) => void
  8. onDispatch: (action: Function) => void
  9. }
  10. const Sidebar = (props: IProps) => {
  11. const { list, currentId } = props
  12. const handleNav = (id: number) => {
  13. props.onSetState( 'currentId', id);
  14. //@ts-ignore
  15. document.getElementById(id + '').scrollIntoView({ block: 'start', behavior: 'smooth' })
  16. }
  17. const sidebarDom = list.map( (item: any) => (
  18. <div key={item.id} className={`m-sidebar-item ${currentId === item.id ? 'active' : ''}`} onClick={() => handleNav(item.id) }>{item.title}</div>
  19. ))
  20. return (
  21. <div className="m-sidebar">
  22. {sidebarDom}
  23. </div>
  24. )
  25. }
  26. const mapStateToProps = (state: IState) => {
  27. return {
  28. list: state.book.list,
  29. currentId: state.book.currentId
  30. }
  31. }
  32. const mapDispatchToProps = (dispatch: Dispatch<any>) => {
  33. return {
  34. onSetState(key: string, value: any) {
  35. dispatch({ type: 'SET_STATE', key, value })
  36. },
  37. onDispatch(action: Function) {
  38. dispatch(action)
  39. }
  40. }
  41. }
  42. export default connect(mapStateToProps, mapDispatchToProps)(Sidebar)

reducer:


  
  1. import { IBookState, IAction } from '../../interface'
  2. const defaultState: IBookState = {
  3. title: '小米书城',
  4. currentId: 0,
  5. isRealScroll: true,
  6. list: [],
  7. myBooks: []
  8. }
  9. const reducer = (state = defaultState, action: IAction) => {
  10. switch (action.type) {
  11. case 'SET_STATE':
  12. let newState = JSON.parse( JSON.stringify(state))
  13. newState[action.key] = action.value
  14. return newState
  15. default:
  16. return state
  17. }
  18. }
  19. export default reducer

actionCreator.js:


  
  1. import { Dispatch } from 'react'
  2. import Api from '../../api'
  3. const list = () => (dispatch: Dispatch<any>) => {
  4. Api.list().then( res => {
  5. if (res.code === 200) {
  6. dispatch({ type: 'SET_STATE', key: 'list', value: res.data })
  7. }
  8. })
  9. }
  10. export default {
  11. list
  12. }

接口:


  
  1. export interface IBookState {
  2. title: string,
  3. currentId: number,
  4. isRealScroll: boolean,
  5. list: any[],
  6. myBooks: any[]
  7. }
  8. export interface IState {
  9. book: IBookState
  10. }
  11. export interface IAction {
  12. type: string,
  13. key: string,
  14. value: any
  15. }

登录页hook写法:


  
  1. import React, { useState, MouseEvent, KeyboardEvent } from 'react'
  2. import { RouteComponentProps } from 'react-router-dom'
  3. import Icon from '../components/Icon'
  4. import Api from '../api'
  5. const Login = (props: RouteComponentProps) => {
  6. const [ username, setUsername ] = useState( 'admin')
  7. const [ password, setPassword ] = useState( '123456')
  8. const [ visible, setVisible ] = useState( false)
  9. const handleVisible = (e: MouseEvent, count: number ) => {
  10. setVisible(!visible)
  11. }
  12. const handleEnter = (e: KeyboardEvent<HTMLInputElement>) => {
  13. if (e.keyCode === 13 ) {
  14. handleLogin()
  15. }
  16. }
  17. const handleLogin = () => {
  18. Api.login({ username, password }).then( res => {
  19. if (res.code === 200) {
  20. localStorage.setItem( 'token', res.data.username)
  21. props.history.push( '/index/home')
  22. }
  23. })
  24. }
  25. return (
  26. <div>
  27. <div>
  28. <input value={username} onChange={(e) => setUsername(e.target.value)} placeholder="请输入用户名" autoFocus> </input>
  29. </div>
  30. <div>
  31. <input value={password} onChange={(e) => setPassword(e.target.value)} onKeyUp={ (e) => handleEnter(e) } placeholder="请输入密码" type={ visible ? 'text' : 'password' }> </input>
  32. <Icon name={ visible ? 'show' : 'hide' } onClick={ (e, count) => handleVisible(e, count) } className="m-login-icon"> </Icon>
  33. </div>
  34. <button onClick={() => handleLogin()}>登录 </button>
  35. </div>
  36. )
  37. }
  38. export default Login

登录页class写法:


  
  1. import React, { Component, ChangeEvent, KeyboardEvent, MouseEvent } from 'react'
  2. import { RouteComponentProps } from 'react-router-dom'
  3. import Icon from '../components/Icon'
  4. import Api from '../api'
  5. interface IState {
  6. username: string,
  7. password: string,
  8. visible: boolean
  9. }
  10. interface IProp extends RouteComponentProps {
  11. }
  12. export default class LoginClass extends Component<IProp, IState> {
  13. constructor(props: IProp) {
  14. super(props)
  15. this.state = {
  16. username: 'admin',
  17. password: '123456',
  18. visible: false
  19. }
  20. }
  21. handleInput(e: ChangeEvent<HTMLInputElement>, field: string) {
  22. // @ts-ignore
  23. this.setState({
  24. [field]: e.target.value
  25. })
  26. }
  27. handleVisible(e: MouseEvent<Element>, count: number) {
  28. let { visible } = this.state
  29. this.setState({
  30. visible: !visible
  31. })
  32. }
  33. handleEnter(e: KeyboardEvent<HTMLInputElement>) {
  34. if(e.keyCode === 13) {
  35. this.handleLogin()
  36. }
  37. }
  38. handleLogin() {
  39. let { username, password } = this.state
  40. Api.login({ username, password }).then( res => {
  41. if (res.code === 200) {
  42. localStorage.setItem( 'token', res.data.username)
  43. this.props.history.push( '/index/home')
  44. }
  45. })
  46. }
  47. render() {
  48. let { username, password, visible } = this.state
  49. return (
  50. <div>
  51. <div>
  52. <input value={username} onChange={(e) => this.handleInput(e, 'username')} placeholder="请输入用户名" autoFocus />
  53. </div>
  54. <div>
  55. <input value={password} onChange={(e) => this.handleInput(e, 'password')} onKeyUp={ (e) => this.handleEnter(e) } placeholder="请输入密码" type={ visible ? 'text' : 'password' }/>
  56. <Icon name={ visible ? 'show' : 'hide' } onClick={ (e, count) => this.handleVisible(e, count) } className="m-login-icon"></Icon>
  57. </div>
  58. <button onClick={() => this.handleLogin()}>登录</button>
  59. </div>
  60. )
  61. }
  62. }

Icon组件hook写法:


  
  1. import React, { MouseEvent } from 'react'
  2. interface IProps {
  3. name: string,
  4. className?: string,
  5. onClick?: (e: MouseEvent, count: number) => void
  6. }
  7. const Icon = (props: IProps) => {
  8. let { name, className = '', onClick = () => {} } = props
  9. return (
  10. <span className={`icon iconfont icon-${name} ${className}`} onClick={(e) => onClick(e, 1)}></span>
  11. )
  12. }
  13. export default Icon

Icon组件Class写法:


  
  1. import React, { Component, MouseEvent } from 'react'
  2. interface IProps {
  3. name: string,
  4. className?: string,
  5. onClick?: (e: MouseEvent, count: number) => void
  6. }
  7. export default class IconClass extends Component<IProps> {
  8. render() {
  9. const { name, className = '', onClick = () => {} } = this.props
  10. return (
  11. <span className={`icon iconfont icon-${name} ${className}`} onClick={(e) => onClick(e, 1)}></span>
  12. )
  13. }
  14. }

ReactElement:


  
  1. import React, { Dispatch, ReactElement } from 'react'
  2. import Header from '../components/Header'
  3. import Footer from '../components/Footer'
  4. import { Switch, Route } from 'react-router-dom'
  5. import { connect } from 'react-redux'
  6. import Home from './Home'
  7. import MyBooks from './MyBooks'
  8. import Me from './Me'
  9. interface IProps {
  10. onSetState: (key: string, value: any) => void
  11. onDispatch: (action: Function) => void
  12. }
  13. const Index = (props: IProps) => {
  14. const renderComponent = (Component: ReactElement, title: string) => {
  15. setTimeout( () => {
  16. props.onSetState( 'title', title)
  17. })
  18. return Component
  19. }
  20. return (
  21. <div className="m-wrap">
  22. <Header> </Header>
  23. <Switch>
  24. <Route path="/index/home" render={() => renderComponent( <Home> </Home>, '小米书城')}> </Route>
  25. <Route path="/index/my_books" render={() => renderComponent( <MyBooks> </MyBooks>, '我的书包')}> </Route>
  26. <Route path="/index/me" render={() => renderComponent( <Me> </Me>, '个人中心')}> </Route>
  27. </Switch>
  28. <Footer> </Footer>
  29. </div>
  30. )
  31. }
  32. const mapStateToProps = () => {
  33. return {
  34. }
  35. }
  36. const mapDispatchToProps = (dispatch: Dispatch<any>) => {
  37. return {
  38. onSetState(key: string, value: any) {
  39. dispatch({ type: 'SET_STATE', key, value })
  40. },
  41. onDispatch(action: Function) {
  42. dispatch(action)
  43. }
  44. }
  45. }
  46. export default connect(mapStateToProps, mapDispatchToProps)(Index)

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

参考链接:

一起来拥抱强大的TypeScript吧--Ts+Vue完全教程

中文手册

英文手册

入门教程

装饰器----阮一峰

Learn React with TypeScript 3(英文版):

链接:https://pan.baidu.com/s/1BriHov6-BRiQTIZlcR3dWw
提取码:7erx

 

 

 

 

 

 

 

 

 

 

 

 

 

 


转载:https://blog.csdn.net/xutongbao/article/details/105532857
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场