【b站ZSEN就是Huzhushan】Typescript入门并在vue项目中使用

课程地址:【Typescript入门并在vue项目中使用】 https://www.bilibili.com/video/BV1A54y117kA/?share_source=copy_web&vd_source=b1cb921b73fe3808550eaf2224d1c155

目录

1 快速了解ts的基础类型

1.1 上

1.2 下

2 vue组件新的写法

2.1 安装vue cli

2.2 通过vue cli初始化项目

2.3 项目文件

2.4 vue-property-decorator组件

 2.4.0 钩子函数

2.4.1 @Component装饰器

知识点1:name属性

知识点2:自定义组件

知识点3:新写法

知识点4:data数据

知识点5:计算属性

知识点6:在模板里显示数据

补充:eslint报错

 知识点7:methods写法

知识点8:计算属性的set方法

2.4.2 @Watch装饰器

2.4.3 @Prop装饰器

1 创建一个自定义组件

2 父组件传值

3 子组件接收参数

2.4.4 @Emit装饰器

1、添加删除按钮

2、向父组件Emit一个事件

3、父组件接收事件

4、子组件传递id供父组件删除用户信息

2.4.5 @Model装饰器 !!!

1、父组件将firstName传给子组件

2、子组件处理

2.4.6 完整代码

3 vuex的ts写法

4 ts后台管理框架


1 快速了解ts的基础类型

1.1 上

布尔类型boolean、数值类型number、字符串类型string、数组Array<T>或T[]、undefined、null、联合类型(ts中的或 | )、任意类型any、空类型void、接口、对象、属性可选、接口继承(继承1个接口,继承多个接口)、ts中的与&。

// 布尔类型
let boo1: boolean = true;
boo = '123';  // 报错

// 数值类型
let num1: number = 123;

//字符串
let str: string = '123';

// 数组
// 写法1
let arr: Array<number> = [1, 2, 3];
// 写法2
let arr2: number[] = [1, 2, 3];

// undefined、null
let _undefined: undefined = undefined;
let _null: null = null;

// ts中的或|,联合类型
// 只能是所有类型中的某一个
let some_var: number | string | boolean | undefined;
// 以下不会报错
some_var = true;
some_var = 'aaa';
some_var = undefined;

// any,不进行类型校验,可以是任意类型
let any_var: any = 123;
// any可以是任何类型,不再进行类型校验
any_var = true;

// void,主要是针对函数,函数没有return任何值,返回值就是void
function func(arg: number): void {

}
func(1)

function func2(arg: string): boolean {
    return false;
}

// 接口,名称预定俗称以I开头,interface
interface IPerson {
    name: string,
    age: number,
    sex: string
}
// 对象:使用接口来定义对象的类型
let obj: IPerson = {
    name: 'zyy',
    age: 18,
    sex: 'male'
}

interface IPerson2 {
    name: string,
    age: number,
    sex?: string // 可选项
}
// 对象:使用接口来定义对象的类型
let obj2: IPerson2 = {
    name: 'zyy',
    age: 18
}

// 接口继承
interface IPerson3 {
    name: string
}
// 继承1个接口
interface ITeacher extends IPerson3 {
    hobby: Array<string>,
    student: string[]
}
let teacher: ITeacher = {
    name: 'zyy',
    hobby: ['a', 'b', 'c'],
    student: ['d', 'e', 'f']
}
// 继承多个接口
interface IPerson4 {
    age: number
}
// 继承多个接口时,逗号分开
interface ITeacher2 extends IPerson3, IPerson4 {
    hobby: Array<string>,
    student: string[]
}
let teacher2: ITeacher2 = {
    name: 'zyy',
    hobby: ['a', 'b', 'c'],
    student: ['d', 'e', 'f'],
    age: 18
}

// ts中的与&
// 具备两个接口的所有属性。
let person4: IPerson3 & IPerson4 = {
    name: 'zyy',
    age: 19
}

1.2 下

接口-属性不确定,类型不确定、实现接口implements、类型断言、非空断言、枚举(反向映射,枚举赋值)、泛型


// 接口
// 属性不确定
interface IPerson5 {
    [propName: string]: any // 索引签名类型
}
let person5: IPerson5 = {
    name: 'zyy',
    age: 19,
    sex: 'female'
}

// implements接口实现
interface IPerson6 {
    name: string,
    age: number,
    sex: string,
    getName: () => string,
    getAge: () => number
}
class Person implements IPerson6 {
    name: string = 'zyy';
    age: number = 18;
    sex: string = 'female';
    getName(): string {
        return this.name;
    };
    getAge(): number {
        return this.age;
    };
    // 类自己的方法
    sayHello(): void {
        console.log('Hello!');
    }
}

// 类型断言
function getLength(str: number | string): number {
    // 类型断言,断言str是string类型
    if ((str as string).length) {
        // 类型断言方式1, 变量后使用as
        // return (str as string).length;
        // 类型断言方式2,变量前使用<>
        return (<string>str).length;
    } else {
        return str.toString().length;
    }
}
// 非空断言
function func3(arg?: string): number {
    // !表示arg一定存在
    return arg!.length;
    // 相当于return arg && arg.length;
    // 即若arg存在,返回arg.length,否则返回null/undefined/NaN
}

// 枚举
enum Color {
    red,
    green,
    yellow
}
// 属性的值从0开始自增
Color.red // 0
Color.green // 1
Color.yellow // 2
// 反向映射
Color[0] //返回 'red'
Color[1] //返回 'green'
Color[2] //返回 'yellow'

// 给枚举赋值
enum Color2 {
    red = 1,
    green,  //2
    yellow  //3
}
enum Color3 {
    red,
    green = 2,  //2
    yellow  //3
}
// 如果前一个枚举值是字符串,后一个枚举属性必须赋值
enum Color4 {
    red,
    green = 'green',
    yellow = 'yellow'
}

// 泛型
//  T表示泛型,一般用T表示,别的字母也可以
function func4<T>(arg: T): void {

}
func4<number>(123);// 定义T为number,则参数只能传number类型的值

2 vue组件新的写法

https://v2.cn.vuejs.org/

初始化一个vue项目。

2.1 安装vue cli

Vue CLI

Installation | Vue CLI

安装命令

npm install -g @vue/cli

在vs code的命令行直接执行上述命令即可。

不知道成功了没。

vue cli安装失败,解决npm ERR! code CERT_HAS_EXPIRED npm ERR! errno CERT_HAS_EXPIRED npm ERR! request to-CSDN博客

2.2 通过vue cli初始化项目

通过vue cli初始化项目。

操作。

步骤1:在目标文件夹下,右键,点击Git Bash Here。

步骤2,输入命令和项目名称

这里up给的命令在后面不能通过键盘上下键进行选择。

解决方法:
这时候将 vue create 项目名 这个指令改为 winpty vue.cmd create 项目名 即可。

步骤3,选择默认还是手动选择,这里选择手动选择。

步骤4:选择特性

使用空格进行选择,其中Babel,TypeScript必选,Router和vuex也选上,其他的可选可不选。

步骤5:选择vue.js的版本。

up视频里没有,应该是那个时候还没有vue3(vue3在2020年9月18日出版的,学习的这个视频是2020年9月19日传到Bilibili上的)。

此处选择2.x。

步骤6:这里up没说原因,就输入个y吧

步骤7:使用Babel,去解析JSX,也输入y。还有选择历史模式,也是yes。

步骤8:校验,选择ESlint + Airbnb config吧

步骤9:是保存的时候校验,还是提交的时候修复,都选。

步骤10:配置文件,是放到单独的文件还是package.json中,这里选择单独文件。

步骤11:是否将当前做的选择保存成一个文件方便下次使用。这里是n,不需要。

然后就开始初始化项目了,安装依赖包等。

此时项目里会多了一个文件夹。

步骤12:安装完成,提示两个命令。

① 进入这个目录

② 然后运行项目。

首先进入这个目录

然后运行项目

然后他就会执行构建

构建完成

项目已经启动,打开下面的地址。

项目启动的页面如下。与之前用vue cli初始化的项目是一样的。但是代码是不一样的。

2.3 项目文件

.d.ts文件,类型声明文件。

tsx结尾的文件,可以写jsx的代码。

vue结尾的文件,表示在ts可以识别.vue结尾的文件。

2.4 vue-property-decorator组件

书接上文,代码是不一样的。

使用vs code打开上面新建的项目文件夹

vue-property-decorator 的装饰器主要有以下几个:
@Component
@Watch 监听
@Prop 子组件接收参数
@Model 与@Prop类似,在子组件传参,可以通过v-model传参,子组件接收参数是通过@Model来接收
@Emit 子组件往父组件传递回调函数

import { Component, Vue } from 'vue-property-decorator';
/*
vue-property-decorator 的装饰器
@Component
@Watch 监听
@Prop 子组件接收参数
@Model 与@Prop类似,在子组件传参,可以通过v-model传参,子组件接收参数是通过@Model来接收
@Emit 子组件往父组件传递回调函数
*/

自定义事件 — Vue.js

浅了解下@Model装饰器

 2.4.0 钩子函数

跟以前一样,在export default ... 里直接写。这里就不写具体的代码了。

2.4.1 @Component装饰器

知识点1:name属性

@Component的name(新写法)相当于export default里的name(老写法)。

知识点2:自定义组件

如果有自定义组件,就写在装饰器@Component的components里。

如果没有自定义组件,可以不写(括号也不需要)

知识点3:新写法

知识点4:data数据

老写法:在export default里,写一个data函数,return一个对象,具体的数据就在return的对象里。

新写法:

知识点5:计算属性

老写法:

新写法:

知识点6:在模板里显示数据

使用vue的模板语法。

效果

补充:eslint报错

报错1:表示字符串应该用单引号而不是双引号。(但是vs code自动会把单引号的字符串改为双引号)

eslint 是一个严格的语法检查工具 ,出现 Strings must use singlequote" ,就是语法检查引起的。

有两种改法:百度安全验证

饮鸩止渴式做法

 知识点7:methods写法

老写法:

新写法:

直接写方法名和方法体,不需要写methods,且methods和计算属性和data都不需要用逗号(,)隔开(写逗号还会报错)。

知识点8:计算属性的set方法

set方法的必要性:当计算属性fullName变化时,对于拼接fullName的firstName和lastName的值也要对应变化。

老写法:

新写法:

modifyFullName是改变fullName的事件处理函数。当fullName改变时,会触发计算属性fullName的set函数,因此firstName和lastName也就会发生变化。

效果

改变之前

点击按钮改变fullName,fullName发生变化,同时firstName和lastName也一起发生变化。

完整代码

<template>
  <div class="about">
    <h1>This is an about page</h1>
    <p>{{ firstName }}</p>
    <p>{{ lastName }}</p>
    <p>{{ fullName }}</p>
    <button @click="modifyFullName">修改fullName</button>
  </div>
</template>

<script lang="ts">
/* eslint-disable */
import { Component, Vue } from "vue-property-decorator";
/*
vue-property-decorator 的装饰器
@Component
@Watch 监听
@Prop 子组件接收参数
@Model 与@Prop类似,在子组件传参,可以通过v-model传参,子组件接收参数是通过@Model来接收
@Emit 子组件往父组件传递回调函数
*/
/*
export default {
  name: "About",
  data() {
    return {
      firstName: 'z',
      lastName: 'yy',
    }
  },
  computed: {
    fullName: {
      get() {
        return this.firstName + ' ' + this.lastName;
      },
      set(val) {
      }
    }
  },
  methods: {
    modifyFullName() {

    }
  }
}
*/
@Component
export default class About extends Vue {
  /* eslint-disable */
  firstName = "z";
  lastName: string = "yy";
  // 计算属性
  get fullName() {
    return this.firstName + " " + this.lastName;
  }
  set fullName(val) {
    // this.fullName变化后,需要对拼接的this.firstName 和 this.lastName进行相应的修改
    const arr = val.split(" ");
    this.firstName = arr[0];
    this.lastName = arr[1];
  }

  modifyFullName() {
    this.fullName = "li si";
  }
}
</script>

2.4.2 @Watch装饰器

在上面知识点8例子的背景下,修改fullName时,firstName和lastName也要进行相应修改。通过watch进行监听。

步骤1:引入Watch装饰器。

步骤2:通过watch进行监听firstName的变化。

说明:过程:点击按钮,修改fullName,然后会执行fullName的set方法,修改firstName和lastName的值。 当firstName修改时,通过watch监听firstName,当firstName修改后马上执行onFirstChange方法(方法随便写)。

2.4.3 @Prop装饰器

在自定义组件里接收参数。

1 创建一个自定义组件

步骤1:components里新建组件User.vue。

2 父组件传值

步骤1:在父组件里引入子组件

import User from "../components/User.vue";

注意:在ts里, 引入的自定义组件的位置要写全,不写".vue"会报错。

在装饰器@Component的components属性里配置自定义组件

步骤2:定义用户列表

用接口来实现数组-用户列表的定义。

在模板里使用user组件循环展示user信息。

3 子组件接收参数

老写法和新写法

补充

子组件user的模板

效果

注意:eslint报错:error Expected linebreaks to be ‘LF‘ but found ‘CRLF‘ linebreak-style

解决:

https://blog.csdn.net/qq_41547882/article/details/115458137

2.4.4 @Emit装饰器

实现对用户信息的单条删除。

1、添加删除按钮

给上面的三个user的右边添加删除按钮。

静态效果

2、向父组件Emit一个事件

步骤1:引入Emit装饰器。

import { Component, Vue, Prop, Emit } from "vue-property-decorator";

步骤2:向父组件Emit一个事件

3、父组件接收事件

添加on-remove事件。

事件处理函数remove,打印一下子组件抛出的值。

打印结果。111就是子组件user.vue传出去的参数。

4、子组件传递id供父组件删除用户信息

步骤1:user在remove的时候传递id。

步骤2:remove方法

步骤3:父组件接收到id,删除对应的用户信息。

严格一点,ts里要声明变量的类型。

效果

删除了中间年龄为19的用户信息。

Emit可以不传事件名,不传的话,事件名就是执行的方法名的改写(加短划线)

举例:添加年龄修改的功能。

1、子组件添加年龄修改按钮

2、向父组件emit一个change-age事件

3、父组件处理change-age事件

以及对应的事件处理函数

结果:

2.4.5 @Model装饰器 !!!

当在子组件修改firstName时,父组件的firstName就会同步修改。

1、父组件将firstName传给子组件

2、子组件处理

步骤1 引入Model

import { Component, Vue, Prop, Emit, Model } from "vue-property-decorator";

步骤2 接收v-model传入的属性

步骤3:input框供用户输入父组件传给子组件的值,绑定点击事件。

input框绑定了onChangeFirName事件处理函数,在修改firName的时候会触发onChangeFirName方法

步骤4:当子组件修改firstName时,会emit一个changeFirstName事件(Model里指定的事件)

步骤5:最后,父组件里的firstName的值就会同步修改,父组件不想要接收事件。

结果。

在输入框修改内容,上面的firstName和fullName也会一起修改。

2.4.6 完整代码

可以在vs code终端里运行该项目,要在该项目文件夹下。(由于eslint的语法检查,这里运行失败了)

上面章节有点多,这里给出完整的代码。

AboutView.vue(作为以上案例的父组件)

<template>
  <div class="about">
    <h1>This is an about page</h1>
    <p>{{ firstName }}</p>
    <p>{{ lastName }}</p>
    <p>{{ fullName }}</p>
    <button @click="modifyFullName">修改fullName</button>

    <!-- 水平线 -->
    <hr />
    <!-- v-bind将item所有的属性都传给子组件User.vue -->
    <user
      v-for="item in userList"
      :key="item.id"
      v-bind="item"
      @on-remove="remove"
      @change-age="changeAge"
      v-model="firstName"
    ></user>
  </div>
</template>

<script lang="ts">
/* eslint-disable */
import { Component, Vue, Watch } from "vue-property-decorator";
import User from "../components/User.vue";
/*
vue-property-decorator 的装饰器
@Component
@Watch 监听
@Prop 子组件接收参数
@Model 与@Prop类似,在子组件传参,可以通过v-model传参,子组件接收参数是通过@Model来接收
@Emit 子组件往父组件传递回调函数
*/
/*
export default {
  name: "About",
  data() {
    return {
      firstName: 'z',
      lastName: 'yy',
    }
  },
  computed: {
    fullName: {
      get() {
        return this.firstName + ' ' + this.lastName;
      },
      set(val) {
      }
    }
  },
  methods: {
    modifyFullName() {

    }
  }
}
*/
interface IUser {
  id: number;
  name: string | number;
  age: number;
  gender?: string;
}
@Component({
  components: {
    User,
  },
})
export default class About extends Vue {
  /* eslint-disable */
  firstName = "z";
  lastName: string = "yy";
  // 用户列表
  userList: Array<IUser> = [
    {
      id: 1,
      name: "zyy",
      age: 18,
      gender: "female",
    },
    {
      id: 2,
      name: "zyy",
      age: 19,
    },
    {
      id: 3,
      name: "zyy",
      age: 20,
    },
  ];
  // 计算属性
  get fullName() {
    return this.firstName + " " + this.lastName;
  }
  set fullName(val) {
    // this.fullName变化后,需要对拼接的this.firstName 和 this.lastName进行相应的修改
    const arr = val.split(" ");
    this.firstName = arr[0];
    this.lastName = arr[1];
  }
  modifyFullName() {
    this.fullName = "li si";
  }
  // 传入要监听的参数
  // 过程:点击按钮,修改fullName,然后执行fullName的set方法,修改firstName和lastName
  // 当firstName修改时,这里通过watch监听firstName,当firstName修改后马上执行onFirstChange方法(方法随便写)
  @Watch("firstName")
  onFirstChange(newVal, oldVal) {
    console.log(oldVal, newVal);
  }
  // 钩子函数
  created() {}

  mounted() {}

  remove(id: number) {
    // 找到要删除的用户的索引值
    const index: number = this.userList.findIndex((user) => user.id === id);
    // 删除
    this.userList.splice(index, 1);
  }

  changeAge(id: number) {
    // 获取要改变年龄的用户
    const user: IUser = this.userList.find((user) => user.id === id);
    // 改变该user的年龄
    user.age++;
  }
}
</script>

User.vue(作为以上案例的子组件)

<template>
  <!-- 显示姓名、性别和年龄 -->
  <div>
    <div>
      firName: <input type="text" :value="firName" @input="onChangeFirName" />
    </div>
    姓名: {{ userName }}, 性别: {{ gender }}, 年龄: {{ age }}
    <button @click="changeAge(id)">年龄+1</button>
    <button @click="remove(id)">删除</button>
  </div>
</template>
<script lang="ts">
import { Component, Vue, Prop, Emit, Model } from "vue-property-decorator";
@Component({
  name: "User",
})
/*
export default {
    props: {
        propsA: Number,
        propsB: [String, Number]
    }
}
*/
export default class User extends Vue {
  get userName() {
    return this.name;
  }
  // 加了个非空断言
  @Prop(Number)
  id!: number;

  @Prop([String, Number])
  name!: string | number;

  // 指定类型
  @Prop({ type: Number })
  age!: number;

  //  有默认值
  @Prop({ type: String, default: "female" })
  gender?: string;

  // 向父组件emit一个on-remove事件
  @Emit("on-remove")
  remove(id: number) {
    // return可以不写
    // 如果没有return的话,默认会把函数的参数传递出去
    // return id;
  }

  @Emit() // Emit括号不写事件,会默认emit一个change-age事件(根据下面的函数名称)
  changeAge(id: number) {}

  // firstName通过v-model传到user里来。
  @Model("changeFirstName", { type: String })
  firName!: string;

  // input框绑定了onChangeFirName事件处理函数,在修改firName的时候会触发onChangeFirName方法
  // 当子组件修改firstName时,会emit一个changeFirstName事件(Model里指定的事件)
  @Emit("changeFirstName")
  onChangeFirName(e: any) {
    // return 修改后的值
    return e.target.value;
  }
}
</script>

3 vuex的ts写法

p7

vuex,暂时没学过,这part可以跳过(以后看了vuex,可以再看看这块)。

(包括一些@Mutation、@Action等等)

4 ts后台管理框架

vue-typescript-admin

介绍 | vue-typescript-admin

是一个后台管理模板,支持typescript,使用了element-ui,也有js版本。

github地址:GitHub - Armour/vue-typescript-admin-template: 🖖 A vue-cli 3.0 + typescript minimal admin template

随便看看。src/views/charts/bar-chart.vue,有学过的一些东西。

有需要可以去了解一下这个框架

  • 16
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值