vue2配置使用typescript教程
本文是vue项目的js升级ts教程,也可以作为vue项目的ts使用教程。项目背景:vue版本:2.6.11基于vue-cli4脚手架生成已配置eslint(配置教程参考:传送门)一、安装依赖vue ts基础:npm i -D typescript @vue/cli-plugin-typescriptts校验相关:npm i -D @typescript-eslint/eslint-plugin @
本文是vue项目的js升级ts教程,也可以作为vue项目的ts使用教程。
项目背景:
- vue版本:2.6.11
- 基于vue-cli4脚手架生成
- 已配置eslint(配置教程参考:传送门)
一、安装依赖
vue ts基础:
npm i -D typescript @vue/cli-plugin-typescript
ts校验相关:
npm i -D @typescript-eslint/eslint-plugin @typescript-eslint/parser @vue/eslint-config-typescript eslint-plugin-import eslint-plugin-node eslint-plugin-promise eslint-plugin-standard
vue ts辅助:
npm i -D vue-class-component vue-property-decorator
二、添加文件
1、src目录添加两个ts声明文件,用于支持ts的类型声明:
shims-tsx.d.ts
import Vue, { VNode } from 'vue'
declare global {
namespace JSX {
// eslint-disable-next-line @typescript-eslint/no-empty-interface
interface Element extends VNode {}
// eslint-disable-next-line @typescript-eslint/no-empty-interface
interface ElementClass extends Vue {}
interface IntrinsicElements {
[elem: string]: any;
}
}
interface Window {
__wxjs_environment: any;
WebViewJavascriptBridge: any;
_czc: any;
}
}
shims-vue.d.ts
declare module '*.vue' {
import Vue from 'vue'
export default Vue
}
2、根目录添加tsconfig.json,用于项目的ts校验
{
"compilerOptions": {
"target": "esnext",
"module": "esnext",
"strict": true,
"jsx": "preserve",
"importHelpers": true,
"moduleResolution": "node",
"experimentalDecorators": true,
"skipLibCheck": true,
"esModuleInterop": true,
"allowSyntheticDefaultImports": true,
"sourceMap": true,
"baseUrl": ".",
"types": [
"webpack-env"
],
"paths": {
"@/*": ["src/*"]
},
"lib": [
"esnext",
"dom",
"dom.iterable",
"scripthost"
]
},
"include": [
"src/**/*.ts",
"src/**/*.tsx",
"src/**/*.vue",
],
"exclude": [
"node_modules",
"dist",
"public",
"build"
]
}
三、使用方式
vue-property-decorator插件使用文档:传送门
1、script标签
要在.vue文件里使用ts,首先要在script标签上添加属性lang=“ts”
例如一个基础的App.vue
<template>
<div id="app">
<router-view/>
</div>
</template>
<script lang="ts">
import { Vue, Component } from 'vue-property-decorator'
@Component
export default class App extends Vue {
}
</script>
<style lang="less">
</style>
- 导出的class类名等同js版导出的name属性
2、data数据
直接用等于号赋值
// ========== js版 ==========
data () {
return {
a: 1,
b: false
}
}
// ========== ts版 ==========
a = 1
b = false
3、computed计算属性
用get的形式
// ========== js版 ==========
computed: {
aa () {
return this.a
}
}
// ========== ts版 ==========
get aa () {
return this.a
}
4、生命周期钩子函数
保持不变,只是不同函数之间不需要用逗号分隔
5、methods方法
不再需要methods属性包裹,里面的方法直接提出来,和声明钩子函数平级(注意方法名别和钩子函数重名了),方法之间也不需要逗号分隔。
// ========== js版 ==========
created () {},
methods: {
getData () {},
setData () {}
}
// ========== ts版 ==========
created () {}
getData () {}
setData () {}
6、自定义组件components、自定义指令directives、过滤器filters
全都写在开头的@Component里
// ========== ts版 ==========
@Component({
components: {},
directives: {},
filters: {}
})
7、props参数接收
通过@Prop定义
// ========== js版 ==========
props: {
title: {
type: String,
default: ''
},
list: {
type: Array,
default () {
return []
}
}
// ========== ts版 ==========
@Prop({ default: '' }) readonly title!: string
@Prop({ default: () => [] }) readonly list!: any[]
8、watch监听
通过@Watch定义
// ========== js版 ==========
watch: {
// 普通监听
list (val, oldVal) {
console.log(val, oldVal)
},
// 深度监听
res: {
handler () {
console.log(val, oldVal)
},
deep: true,
immediate: false
}
}
// ========== ts版 ==========
@Watch('list')
onWatchList (val, oldVal) { // 方法名没要求,但是要放在相应的@Watch下面,一一对应
console.log(val, oldVal)
}
@Watch('res', { deep: true, immediate: false })
onHandleRes (val, oldVal) {
console.log(val, oldVal)
}
9、computed的get set 版
通过@PropSync定义
// ========== js版 ==========
props: {
// 父组件通过isShow.sync传递
isShow: {
type: boolean,
default: false
}
},
computed: {
isShowModal: {
get () {
return this.isShow
},
set (val) {
this.$emit('isShow:update', val)
}
}
}
// ========== ts版 ==========
@PropSync('isShow', { default: false }) isShowModal!: boolean
10、mixins混入
直接上双混入:
- js版
// mixins1.js
export default {
created () {
console.log(1)
}
}
// mixins2.js
export default {
created () {
console.log(2)
}
}
// index.vue
<template>
<div id="index"></div>
</template>
<script>
import mixins1 from './mixins1'
import mixins2 from './mixins2'
export default {
mixins: [mixins1, mixins2]
}
</script>
- ts版
// mixins1.ts
import { Component, Vue } from 'vue-property-decorator'
@Component
export default class mixins1 extends Vue {
created () {
console.log(1)
}
}
// mixins2.ts
import { Component, Vue } from 'vue-property-decorator'
@Component
export default class mixins2 extends Vue {
created () {
console.log(2)
}
}
// index.vue
<template>
<div id="index"></div>
</template>
<script lang="ts">
import { Component, Prop, Mixins } from 'vue-property-decorator'
import mixins1 from './mixins1'
import mixins2 from './mixins2'
@Component
export default class Index extends Mixins(mixins1, mixins2) {
}
</script>
11、vuex
推荐使用插件vuex-class 官方文档
npm i vuex-class -S
以带命名空间namespace的为例:
import { Component, Vue } from 'vue-property-decorator'
import { namespace } from 'vuex-class'
const userModule = namespace('user')
@Component
export default class Index extends Vue {
@userModule.Getter isLogin!: boolean // 使用this.isLogin指代vuex的user模块里getters的同名isLogin
}
四、报错处理
1、引入第三方插件报无法找到模块
需要在shims-vue.d.ts文件里声明。
- 例如: import md5 from ‘js-md5’,
报错信息:无法找到模块"js-md5"的声明文件
解决方法:在shims-vue.d.ts里添加
declare module 'js-md5' {
import md5 from 'js-md5'
export default md5
}
2、this.$ 报错 does not exist on type
常见于给vue实例添加的自定义属性上,比如 $toast $http $loading
- 例如:this.$loading.show()
报错信息:Property ‘loading’ does not exist on type ‘Index’.
解决方法:shims-tsx.d.ts里添加以下声明(以 $loading为例)
declare module 'vue/types/vue' {
interface Vue {
$loading: { show: (text?: string) => void; hide: () => void }; // 具体类型以你自己的为准,或者直接用any
}
}
3、引入路径带@时报错
报错信息:找不到模块…或其相应的类型声明。
可能的原因有很多,按照以下方法依次排查处理:
(1)配置tsconfig.json
- 检查项目根目录tsconfig.json文件的path属性是否正确配置了@的路径
"paths": {
"@/*": ["src/*"]
},
- 如果@路径名是动态的,解决方法: shims-vue.d.ts里添加模块声明。
例如 import api from ‘@/utils/api’ 报错,就按下面方式添加:
declare module '@/utils/api' {
import api from '@/utils/api'
export default api
}
(2).ts文件路径不能带后缀名,.vue文件路径需要加上后缀名
ts里引入.ts文件时路径不要加后缀名,引入.vue文件时路径需要带上.vue后缀名
import apis from '@/utils/api'
import ruleModal from '@/components/rule.vue'
4、其他各种疑难杂症
那就试试vscode工作区的配置:
- 将项目文件夹拖进vscode里,以工作区的形式展示,然后将该项目拖到顶部,使其排在工作区的第一位,如图所示的dyd-h5项目,很多莫名其妙的问题都能通过这种方式解决:
五、结语
vue 2.x的版本需要引入第三方插件使用class类的形式才能较好的配合使用ts,写起来还是比较繁琐的,而已经发布了正式版的vue 3.0对ts的支持比较完全,而且可以使用function形式使用ts,类似于react的hooks,function形式更加简单方便,如果是新开的项目还是推荐直接上vue 3.0吧。
六、附录
1、.eslintrc.js
module.exports = {
root: true,
env: {
browser: true,
node: true
},
extends: [
'plugin:vue/essential',
'@vue/standard',
'@vue/typescript/recommended'
],
parserOptions: {
ecmaVersion: 2020
},
globals: {
_czc: true
},
rules: {
'no-console': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
'no-debugger': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
'camelcase': 'off',
'comma-dangle': 'off',
'@typescript-eslint/no-explicit-any': 'off',
'@typescript-eslint/camelcase': 'off',
'@typescript-eslint/no-empty-function': 'off',
'lines-between-class-members': 'off',
'@typescript-eslint/no-this-alias': [
"error",
{
"allowDestructuring": true,
"allowedNames": ["that", "self"]
}
]
},
}
更多推荐
所有评论(0)