Vue2 使用 typescript 教程

Vue2 + TypeScript 核心是用装饰器(class 语法)Vue.extend 写组件,配合vue-class-componentvue-property-decorator提供类型与装饰器支持Vue.js。下面从环境搭建→组件写法→Props / 生命周期→Vuex / 路由→常见坑,给你一套完整可落地教程。

一、环境搭建

1:Vue CLI 直接创建
bash 复制代码
# 安装/更新 CLI
npm install -g @vue/cli

# 创建项目
vue create vue2-ts-demo
# 选择:Manually select features → 勾选 TypeScript → 选择 Vue 2.x
# 后续可默认,创建完成后进入目录
cd vue2-ts-demo
npm run serve

生成关键文件:

  • tsconfig.json:TS 编译配置
  • src/shims-vue.d.ts:让 TS 识别 .vue 文件
  • src/shims-tsx.d.ts:支持 TSX 语法
2:现有 Vue2 项目接入 TS

安装依赖

bash 复制代码
npm install typescript ts-loader --save-dev
npm install vue-class-component vue-property-decorator --save

配置 tsconfig.json(根目录)

bash 复制代码
{
  "compilerOptions": {
    "target": "es5",
    "module": "es2015",
    "strict": true,
    "experimentalDecorators": true,
    "allowSyntheticDefaultImports": true,
    "moduleResolution": "node"
  },
  "include": ["src/**/*"],
  "exclude": ["node_modules"]
}

配置 vue.config.js(支持 TS 加载)

bash 复制代码
module.exports = {
  chainWebpack: config => {
    config.resolve.extensions.add('.ts').add('.tsx')
    config.module
      .rule('ts')
      .test(/\.(ts|tsx)$/)
      .use('ts-loader')
      .loader('ts-loader')
      .options({ appendTsSuffixTo: [/\.vue$/] })
  }
}

类型声明文件

bash 复制代码
// src/shims-vue.d.ts
declare module '*.vue' {
  import Vue from 'vue'
  export default Vue
}

二、组件写法(Class + 装饰器(@Component/@Prop/@Computed))

1. 基础组件(@Component
bash 复制代码
<!-- src/components/Hello.ts -->
<template>
  <div>
    <h1>{{ msg }}</h1>
    <button @click="sayHello">点击</button>
  </div>
</template>

<script lang="ts">
import Vue from 'vue'
import Component from 'vue-class-component'

@Component
export default class Hello extends Vue {
  // 数据:直接声明类型+初始值
  msg: string = 'Hello Vue2 + TS'

  // 方法:直接写,自动绑定 this
  sayHello(): void {
    alert(this.msg)
  }
}
</script>
  1. Props 类型(@Prop
bash 复制代码
<script lang="ts">
import Vue from 'vue'
import Component from 'vue-class-component'
import { Prop } from 'vue-property-decorator'

@Component
export default class User extends Vue {
  // 基础类型
  @Prop() id: number
  // 带默认值
  @Prop({ default: '匿名' }) name: string
  // 必传+校验
  @Prop({ type: String, required: true }) gender!: string
}
</script>
  1. 计算属性(@Computed
bash 复制代码
import { Computed } from 'vue-property-decorator'

@Component
export default class User extends Vue {
  firstName: string = '张'
  lastName: string = '三'

  @Computed()
  get fullName(): string {
    return this.firstName + this.lastName
  }
}
4. 生命周期(直接写方法)
bash 复制代码
@Component
export default class Hello extends Vue {
  created(): void {
    console.log('组件创建')
  }
  mounted(): void {
    console.log('组件挂载')
  }
}

三、Vue.extend 写法(无装饰器)

适合不想用装饰器的场景:

bash 复制代码
import Vue from 'vue'

export default Vue.extend({
  data() {
    return { msg: 'Hello' as string }
  },
  methods: {
    greet(name: string): string {
      return `Hi ${name}`
    }
  }
})

四、Vuex 与 TypeScript

1. 定义 State
bash 复制代码
// src/store/index.ts
import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

interface State {
  count: number
  user: { name: string; age: number }
}

export default new Vuex.Store<State>({
  state: {
    count: 0,
    user: { name: '李四', age: 20 }
  },
  mutations: {
    ADD_COUNT(state) {
      state.count++
    }
  }
})
  1. 组件中使用 Vuex
bash 复制代码
<script lang="ts">
import Vue from 'vue'
import Component from 'vue-class-component'
import { mapState, mapMutations } from 'vuex'

@Component({
  computed: { ...mapState(['count', 'user']) },
  methods: { ...mapMutations(['ADD_COUNT']) }
})
export default class Counter extends Vue {
  // 直接使用 this.count / this.user
}
</script>

五、路由与 TypeScript

bash 复制代码
// src/router/index.ts
import Vue from 'vue'
import Router from 'vue-router'
import Home from '@/components/Home.vue'

Vue.use(Router)

export default new Router({
  routes: [
    {
      path: '/',
      name: 'Home',
      component: Home,
      meta: { title: '首页' } // 可扩展类型
    }
  ]
})

六、常见问题与避坑

  1. this 隐式 anytsconfig.json 开启 strict: trueVue.js
  2. 找不到 .vue 模块 :检查 shims-vue.d.ts 是否正确声明
  3. 装饰器报错 :确保 experimentalDecorators: true
  4. Props 类型不生效 :使用 @Prop 装饰器而非原生写法Vue.js
相关推荐
郭老二1 小时前
【前端】vue3:编译步骤
前端
不在逃避q2 小时前
Trae/Vs Code/Cursor命令行无法跑npm命令
前端·arcgis·npm
夏殇之殁2 小时前
包中创建自定义列表项。 . 使用自定义列表项进行数据绑定 . 将天气预报数据保存到本地内存表,通过LiveBindings进行显示。 ...
服务器·前端·javascript
The Chosen One9852 小时前
高进度算法模板速记(待完善)
java·前端·算法
陈随易2 小时前
MoonBit抓包模块pcap,查看电脑的每一次联网通信
前端·后端·程序员
新中地GIS开发老师3 小时前
WebGIS开发学生作品|低空航天管理与航线规划系统
前端·javascript·webgis·三维gis开发
用户059540174464 小时前
大模型对话记忆持久化踩坑实录:用 Playwright 自动化测了 300 次,终于揪出会话丢失的真凶
前端·css
丙氨酸長鏈4 小时前
Web前端入门第 问:JavaScript 一个简单的 IndexedDB 数据库入门示例
前端·javascript·数据库
kyriewen5 小时前
面试官让我手写虚拟列表——AI生成的版本,快速滚动几下就白屏了
前端·javascript·面试
IT_陈寒5 小时前
Vite热更新失效?你可能漏了这个配置
前端·人工智能·后端