通过vue-cli创建uniapp的ts模板实践踩坑
开发环境
- node版本:LTS(推荐使用nvm或nvs等node版本控制工具)
- vue/cli: lastest
开始
基础步骤参照uni-app官网,模板选择默认typescript模板。
通过vue-cli命令行
npm i -g @vue/cli
vue create -p dcloudio/uni-preset-vue my-project
cd ./my-project
一般还需要安装@types/uni-app、node-sass、sass-loader。
鉴于node-sass安装麻烦,这里使用sass推荐的dart-sass。
dart-sass理论上可以安装最新版,但sass-loader因vue-cli所以需要支持webpack4的版本。
@types/uni-app提供uni-app语法提示。
yarn add -D @types/uni-app sass sass-loader@10.2.0
注意@dcloud的编译插件不适用^
或*
前置符号控制版本,若使用,则会安装alpha版本而不是稳定版本
eslint + prettier
由于原项目是js,现正慢慢向ts重构,所以会配置js/ts/vue/vue lang=ts文件的代码检查和风格规范。主要的插件:@typescript-eslint, eslint-plugin-vue, prettier。
vue-cli提供的eslint插件有部分配置不适用于该项目,于是自己配置,依赖如下:
{
"devDependencies": {
"@typescript-eslint/eslint-plugin": "^4.20.0",
"@typescript-eslint/parser": "^4.20.0",
"eslint": "^7.32.0",
"eslint-config-prettier": "^8.3.0",
"eslint-plugin-prettier": "^3.3.1",
"eslint-plugin-vue": "^7.19.1",
"prettier": "~2.4.1"
}
}
关于eslint和prettier的配置不多赘述,直接贴代码。记得加上.eslintignore和.prettierignore。配置完后vue-cli会自动使用
// .eslintrc.js
module.exports = {
root: true,
env: {
node: true,
es6: true,
},
// 主要parser解析vue
parser: 'vue-eslint-parser',
parserOptions: {
// 下级parser解析vue中的ts
parser: '@typescript-eslint/parser',
ecmaVersion: 'latest',
},
// 后方扩展会覆盖前方扩展,因此prettier最后
extends: [
'eslint:recommended',
'plugin:vue/recommended',
'plugin:@typescript-eslint/eslint-recommended',
'plugin:prettier/recommended',
'eslint-config-prettier',
],
rules: {
'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off',
// 个人倾向 PascalCase 格式的标签,方便直接cv搜索和定位
'vue/component-name-in-template-casing': [
'warn',
'PascalCase',
{
registeredComponentsOnly: true,
ignores: [],
},
],
},
// 此处是vue-cli的eslint插件针对ts变量声明的错误检查修正
overrides: [
{
files: ['*.vue'],
rules: {
// TODO maybe work wrongly with type definitions in <script lang='ts'>
'no-undef': 'off',
},
},
{
files: ['*.ts'],
rules: {
// The core 'no-unused-vars' rules (in the eslint:recommeded ruleset)
// does not work with type definitions
'no-unused-vars': 'off',
},
},
],
globals: {
uni: true,
getApp: true,
getCurrentPages: true,
wx: true,
weex: true,
my: true,
uniCloud: true,
plus: true,
},
}
// .prettierrc
{
"tabWidth": 2,
"useTabs": false,
"semi": false,
"bracketSameLine": false,
"singleQuote": true,
"printWidth": 80,
"endOfLine": "lf"
}
TypeScript 支持
可以先看看官方文档,这里只列出部分模板必须要处理的坑。
uni-app的TypeScript 支持,Vuejs的TypeScript 支持
- 类型定义文件由 @dcloudio/types 模块提供,安装后请注意配置 tsconfig.json 文件中的 compilerOptions > types 部分,如需其他小程序平台类型定义也可以安装,如:miniprogram-api-typings、mini-types。
- 如果需要添加 Vue 实例方法,即通过把它们添加到 Vue.prototype 上,还需要在ts声明文件上添加声明,该特性被称为模块补充。例如新建个vue.d.ts在/src下。如果编辑器依旧报错,尝试重启。
// vue.d.ts
import Vue from 'vue'
declare module "vue/types/vue" {
interface Vue {
$api: AnyObject;
$toast: () => void;
$config: AnyObject;
}
}
- 在 vue 文件的 script 节点声明 lang=“ts” 后,该 vue 文件 import 进来的所有 vue 组件,均需要使用 ts 编写。
- 编写组件时需要使用 Vue.component 或 Vue.extend 定义组件。
- 因为 Vue 的声明文件天生就具有循环性,TypeScript 可能在推断某个方法的类型的时候存在困难。可能需要在 render 或 computed 里的方法上标注返回值。不然ts会对this做出错误判断而报错。
- 标注 Prop。如果发现校验器并没有得到类型推导或命名补全不工作,用预期的类型标注参数可能会解决这类问题。
<script lang="ts">
import Vue, { PropType } from 'vue'
import myComponent from '@/component/my-component/my-componet' // import组件必须用ts编写
interface ComplexMessage {
title: string,
okMessage: string,
cancelMessage: string
}
export default Vue.extend({
components: { myComponent },
props: {
message: {
type: Object as PropType<ComplexMessage>,
required: true,
validator (message: ComplexMessage) {
return !!message.title;
}
}
},
methods: {
// 方法有返回值时,需要标注有 `this` 参与运算的返回值类型
greet (): string {
return this.msg + ' world'
}
},
computed: {
// 需要标注
greeting(): string {
return this.greet() + '!'
}
},
})
</script>
pages.json的模块化
注意:APP和小程序只有编译时起效,H5端运行时可通过路由插件动态配置路由表
pages.json的模块化及模块热重载
待解决的坑
- 使用ts时App.vue可能无法正常工作的问题
- 发现声明@dcloud/types有遗漏。对于缺少或者错误的类型定义,可以自行在本地新增或修改并同时报告给官方请求更新。
- Vetur不能通过settings.json中给files.associations添加"*.nvue": "vue"的方法来为.nvue提供语法支持。幸好暂时没有发版APP的需求。
转载请注明出处。