如何用 TypeScript 编写 Vue 项目

TypeScript

TypeScript 是 JavaScript 的一个超集,大家可以理解为是 JavaScript 的另一种写法。它可以通过 TypeScript 编译器或 Babel 转译为 JavaScript 代码。

参考文档
龙的读书笔记

TypeScript 的优缺点

优点:

  • 类型系统实际上是最好的文档
  • 在代码编写时就会提示大部分错误
  • 大大增强了编辑器和开发工具的功能,有强大的代码补全和提示
  • 他是 JavaScript 的超集,可以直接讲 js 文件重命名为 ts 文件
  • 既是编译器提示了错误,但是仍然可以生成 JavaScript 文件

缺点:

  • 有一定的学习成本,他的接口、泛型等概念对于前端工程师理解起来可能有困难
  • 短期开发会增加开发成本,由于有各种类型声明

TypeScript 与 Javascript 的区别

TypeScript 中的数据要求带有明确的类型,JavaScript 不要求。

let a: string = "hello";
console.log(a.length);

// 编译成 JS 后的代码为

var a = "hello";
console.log(a.length);

TypeScript 中变量被限制了类型之后,就无法访问该类型中不存在的属性或方法,但 js 中可以

// 一段可以执行的js
let a = 100;
if (a.length !== undefined) {
  console.log(a.length);
} else {
  console.log("no length");
}

// 我们将上面的js用ts重写
let a: number = 100;
if (a.length !== undefined) {
  // error TS2339: Property 'length' does not exist on type 'number'.
  console.log(a.length);
} else {
  console.log("no length");
}
// 在ts中变量被声明类型后就不能使用不属于它的方法,否则会报错

基础数据类型

除了经典的:布尔值 数字 字符串 数组 null underfined object
TypeScript 还有:元组 枚举 any void Never

TypeScript 声明时定义了类型,后续使用中不可以改变类型

//布尔值
let bool: boolean = true;

//数字
const num: number = 1;

//字符串
const username: string = "longbao1";

//数组
let arr: number[] = [1, 2, 3]; //这是一个数字数组
let arr1: string[] = ["1,2,3"]; //这是一个字符串数组

//数组泛型写法
let arr2: Array<string> = ["1"];

//元组
// 元组类型允许表示一个已知元素数量和类型的数组,各元素的类型不必相同
let x: [string, number] = ["hello", 10];

//枚举类型
enum Color {Red, Green, Blue}
let c: Color = Color.Green;//一个序号和值相互对应的对象。
console.log(c);

上面仅仅是 ts 中一些简单的类型,还有一些比较复杂的类型,大家可以自己了解。
参考文档

听到这里小伙伴们可能已经感觉用 TypeScript 来编写程序好麻烦,各种声明类型。实际上在 TypeScript 里存在类型推论。也就是说在有些没有明确指出类型的地方,类型推论会帮助提供类型。在有些时候我们可以省略掉对类型的声明。

npm install -g typescript全局安装 ts 编译工具
tsc 文件名.ts在文件目录内运行命令行,将 ts 文件编译为 js 文件

函数

上面我们理解了如何定义一个变量,下面简单的介绍一下如何声明一个函数

//定义函数参数类型
function add(x: number, y: number): number {
  //返回值类型
  return x + y;
}

//添加?来声明可选参数
function buildName(firstName: string, lastName?: string) {
  if (lastName) return firstName + " " + lastName;
  else return firstName;
}

其他

在 TypeScript 中还有许多的知识,例如:接口、类、继承、泛型、装饰器。由于时长的限制可能就不进行逐一介绍了,简单介绍下面可能用到的一些。

Vue 与 typescript

详见git 文档

由于 Vue2 底层的缘故,可能对 ts 的使用并不非常友好,在代码提示上还不够方便强大。

开始一个项目

改造现有的 vue 项目

  • vue create vue_and_typescript
  • npm i vue-class-component vue-property-decorator
  • npm i ts-loader typescript tslint tslint-loader tslint-config-standard
  • 然后进行一系列的配置

包说明:
vue-class-component vue 官方的 ts 支持包
vue-property-decorator 对 ts 支持包更好封装的装饰器
ts-loader webpack ts 解释器
typescript ts 核心
tslint 语法检查器
tslint-loader webpack 语法检查器
tslint-config-standard 语法规则包


创建新的 vue 项目

  • 在创建项目时手动创建,选中 TypeScript 这一项,就可以创建出支持 ts 的 vue 项目。

文件构造:

  • shims-tsx.d.ts :ts 的声明文件,在 ts 可以写 jsx
  • shims-vue.d.ts 声明在 ts 导入 vue 组件
  • tsconfig.json 配置文件
// 文件结构
<template>
  <div id="app">
    <HelloWorld msg="Welcome to Your Vue.js + TypeScript App"/>
  </div>
</template>

<script lang="ts">
import { Component, Vue } from 'vue-property-decorator';
import HelloWorld from './components/HelloWorld.vue';

//Component 装饰器,这个装饰器即便没有内容也不能删除
@Component({
  // 组件注册
  components: {
    HelloWorld,
  },
export default class App extends Vue {
}
})
</script>

装饰器

类装饰器

//装饰器内返回一个函数一般就可以传参
function demoDecorator(countValue: number) {
  return function (target: any) {
    // console.log();
    target.prototype.count = countValue;
  };
}

@demoDecorator(1000) //装饰器直接写在类的前面,就可以装饰这个类
class Greeter {
  greeting: string;
  constructor(message: string) {
    this.greeting = message;
  }
}

const greeter: any = new Greeter("lucy");
console.log(greeter);

// 返回值
// Greeter
// greeting: "lucy"
// __proto__:
// count: 1000
// constructor: ƒ Greeter(message)
// __proto__: Object

方法装饰器

//targetPrototype 类的原型对象、methodName方法名,方法的描述、desc.value就是方法本身
function showPonitDec(param?: string) {
  return function (targetPrototype: any, methodName: any, desc: any) {
    // 首先将获取到的函数存储下来
    const oDescValue = desc.value;
    //替换方法本身。参数传递
    desc.value = function (...arg: any[]) {
      //判断是否传递了事件名、没传递就是事件名相同省略了,
      const eventName = param ? param : methodName;
      console.log(eventName);
      //接收父级传递的自定义函数,这是@Emit的核心
      this.$emit(eventName, ...arg);
      // 运行函数本身代码,实现了函数合并的效果
      oDescValue.apply(this, arg);
    };
  };
}
class Point {
  x: number;
  y: number;
  constructor(x: number, y: number) {
    this.x = x;
    this.y = y;
  }
  //没有传递事件名
  @showPonitDec()
  //传递了参数
  showPoint(id: string) {
    console.log("old1" + id);
  }
}
const point = new Point(1, 2);
point.showPoint("dsvfsdfh");

属性装饰器

// 属性装饰器
function Prop(param?:string){
    // targetPrototype 类的原型对象
    // propName 属性名
    return function(targetPrototype:any,propName:any){
        //可传可不传
        targetPrototype[propName]=param?param:propName
            // 接收prop的值并赋值,实现@Prop的功能
            // targetPrototype[propName]=this[param?param:propName]
    }
}

class ColorPoint{
    x:number
    y:number
    @Prop('col1or11') color!:string
        constructor(x:number,y:number){
            this.x=x
            this.y=y
        }

}
const colorPoint =new ColorPoint(1,2)
console.log(colorPoint.color);

而我们刚刚见到的@Component 其实就是一个类装饰器,将组件装饰到的它下面的对象上。

ts 中 vue 各部分写法

ts 中的 prop 传递数值
//传递
    <TodoWrap title="i am title" :count.sync="count" />

//需要在接收prop的页面导入prop
import { Component, Vue, Prop, PropSync } from "vue-property-decorator";
@Component
export default class TodoWrap extends Vue {
  @Prop(String) title!: string;
  @PropSync("count", { type: Number }) syncedCount!: number;
//接收的变量名以及类型

  //在ts中定义函数直接定义,不需要有 methods
  changecount() {
    this.$emit("update:count", 20000);
  }
}

实际上@Prop 和@PropSync 就是属性装饰器

定义函数,传递函数
//App定义函数传给下级组件
export default class App extends Vue {
  count = 100;
  //定义函数
  handleClick(value: number) {
    console.log(value);
    this.count = value;
  }
}
//  @handle-click="handleClick" 传递需要用驼峰

//组件接收函数
 @Emit("handle-click")
  changeCountNew(value: number) {}
  //一个函数对应一个Emit,Emit也需要导入
  // 可以理解为将两个函数合并了
生命周期
@Component({
created(){}
})

@Watch

侦听器

  //可以对一个数据监听多次,相互之间不会覆盖
  @Watch("question", { immediate: true /*(监听配置) */ })
  //监听函数
  onQuestionChange2(newValue: string, oldValue: string) {
    console.log(newValue);
  }

小结

装饰器语法的使用
@Component :

  • 内部可以写组件注册
  • 生命周期
  • 计算属性

@Prop
@Emit
@PropSync
@Model
@VModel(与 ModelSync 功能相似)
@ModelSync
@Watch

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值