你在寻找Vue3移动端项目框架嘛?请看这里

vue

现在web开发变得更加美妙高效,在于开发工具设计得更好了,丰富性与易用性,都有所提高。丰富性带来了一个幸福的烦恼,就是针对实际应用场景,如何选择工具 ?

1. Vue Cli和Vite之间的选择

Vite的开发环境体验好,基于浏览器原生ES6 Modules提供的功能,不对ES高版本语法进行转译,省略掉耗时的打包流程, 可是考虑到:

1) 项目要用到真机调试功能,开发环境下调试代码时不能使用ES高版本的语法,用着不顺畅。

后面发现可用@vitejs/plugin-legacy解决此问题。

import legacy from \'@vitejs/plugin-legacy\';

2) 受制于历史项目包袱,感受到Vite的一些痛点:

  • Vite最新版2.7.x版本自带的less-loader, 将背景色的rgba属性转换成四位16进制在有些手机上存在兼容性问题。
  • 与某些第三方工具库(比如说Cache-Router)不兼容,编译会报错。
  • Vite的缓存机制,有时候让人有些困惑,代码修改了,重启之后都不生效,要手动删除node_modules下的.vite文件夹才生效。 
  • 给命令行动态添加自定义参数不太方便。
  • Vite不支持装饰器语法,而有的第三方库用到了装饰器语法

3) Vite脚手架默认不集成TypeScript,Vue-Router,Vuex功能,使用起来不太方便

4) Vue Cli作为久经考验的成熟构建工具,稳定坑少,使用者众多,在生态环境和插件数量方面更好。

所以最终选择vue-cli最为Vue项目的脚手架。若是新项目,个人还是比较推荐使用Vite,构建速度确实快。

安装最新版本vue脚手架

npm install -g @vue/cli@next

安装成功后通过查看版本命令,确认是否安装成功

vue -V

@vue/cli 5.0.0-rc.1

2 创建vue3项目

vue create vue3-demo

Vue CLI v5.0.0-rc.1
? Please pick a preset:
  Default ([Vue 2] babel, eslint)
  Default (Vue 3) ([Vue 3] babel, eslint) // 不选择默认的vue3配置,是因为没有vue-router+typescript功能,需要自己引入
> Manually select features // 手动选择特性

Vue CLI v5.0.0-rc.1

? Please pick a preset: Manually select features

? Check the features needed for your project: (Press <space> to select, <a> to toggle all, <i> to invert selection, and <enter> to proceed)

>(*) Choose Vue version

(*) Babel // 添加babel

(*) TypeScript // 添加类型约束功能

( ) Progressive Web App (PWA) Support

(*) Router // 添加路由功能

(*) Vuex // 添加状态管理功能

(*) CSS Pre-processors // 添加样式预编译功能

(*) Linter / Formatter // 添加代码质量校验提示和格式化功能

( ) Unit Testing

( ) E2E Testing

Vue CLI v5.0.0-rc.1

? Please pick a preset: Manually select features

? Check the features needed for your project: Choose Vue version, Babel, TS, Router, Vuex, CSS Pre-processors, Linter

? Choose a version of Vue.js that you want to start the project with

2.x

> 3.x // 选择vue3

Vue CLI v5.0.0-rc.1

? Please pick a preset: Manually select features

? Check the features needed for your project: Choose Vue version, Babel, TS, Router, Vuex, CSS Pre-processors, Linter

? Choose a version of Vue.js that you want to start the project with 3.x

? Use class-style component syntax? (y/N) N // 是否使用class组件语法, ,选N 项目中用Composition API

 为了在Vue中使用TypeScript中,许多开发者选择了Class-Style Component 解决方案,时至今日,还有另外一个方案,Composition API 撰写的代码会完美享用类型推导,并且也不用做太多额外的类型标注。这也同样意味着你写出的 JavaScript 代码几乎就是 TypeScript 的代码。即使是非 TypeScript 开发者也会因此得到更好的 IDE 类型支持而获益。

常规风格

export default {

data(){

return {

selectOptions: [\'A1\', \'A2\'],

results: [],

// ...

}

}

}

class 组件风格

import { Vue, Component } from \'vue-property-decorator\'

@Component

export default class Game extends Vue {

// 定义data

private selectOptions = [\'A1\', \'A2\']

private results: string[] = []

...

}

? Use class-style component syntax? Yes

? Use Babel alongside TypeScript (required for modern mode, auto-detected polyfills, transpiling JSX)? Yes // 是否使用babel工具自动为转换后的 TypeScript 代码注入 polyfiills,此处选择 Y

? Use history mode for router? (Requires proper server setup for index fallback in production) Yes // 使用history网址路径风格,hash路径有点丑陋

? Pick a CSS pre-processor (PostCSS, Autoprefixer and CSS Modules are supported by default): Less // sass在国内安装经常出错,所以选less

? Pick a linter / formatter config: Prettier // 校验配置选择 eslint+prettier组合,沿袭项目使用习惯

? Pick additional lint features: Lint on save // 保存代码时校验代码质量, 提交代码时才去校验代码质量有些滞后

? Where do you prefer placing config for Babel, ESLint, etc. In dedicated config files // 将Babel,ESlint等配置文件从package.json中独立出来,因为json文件不能写注释

? Save this as a preset for future projects? Y // 将此配置保存起来,用于将来的项目 ,下次用vue-cli生成项目时,可以看到之前保存的配置项

启动服务

cd vue3-demo && yarn serve

在VSCode中打开app.vue发现文件中有许多红色的告警波浪线,安装Volar扩展,,绝大多数语法报错消失。顺便说一下为什么要使用Volar扩展,Vetur对<script setup>里面定义的响应式变量支持度不够好。

<script setup>

// ...

// 仅用于template,未在script中被使用,会报 count is declared but its value is never read.Vetur(6133)

const count = ref(1)

//...

</script>

3 配置vue文件保存时自动格式化

代码美化功能,是一个重要的影响开发体验的指标。书写潦草的代码,按下Ctrl+S保存之后,瞬间变成整洁有序, 这种视觉感受,让人神清气爽。

在项目下新建.vscode/settings.json,内容如下: 

{

// ...

"editor.formatOnSave": true,

"editor.defaultFormatter": "esbenp.prettier-vscode",

"[vue]": {

"editor.defaultFormatter": "johnsoncodehk.volar"

},

"[json]": {

"editor.defaultFormatter": "vscode.json-language-features"

},

// ...

}

修改项目下的.prettierrc文件为.prettierrc.js, 内容如下:

module.exports = {

// 1.一行代码的最大字符数,默认是80(printWidth: <int>)

printWidth: 120,

// 2.tab宽度为2空格(tabWidth: <int>)

tabWidth: 2,

// 3.是否使用tab来缩进,我们使用空格(useTabs: <bool>)

useTabs: false,

// 4.结尾是否添加分号

semi: true,

// 5.使用单引号(singleQuote: <bool>)

singleQuote: true,

// 6.object对象中key值是否加引号(quoteProps: "<as-needed|consistent|preserve>")as-needed只有在需求要的情况下加引号,consistent是有一个需要引号就统一加,preserve是保留用户输入的引号

quoteProps: \'as-needed\',

// 7.在jsx文件中的引号需要单独设置(jsxSingleQuote: <bool>)

jsxSingleQuote: false,

// 8.尾部逗号设置,es5是尾部逗号兼容es5,none就是没有尾部逗号,all是指所有可能的情况,需要node8和es2017以上的环境。(trailingComma: "<es5|none|all>")

trailingComma: \'all\',

// 9.object对象里面的key和value值和括号间的空格(bracketSpacing: <bool>)

bracketSpacing: true,// 10.箭头函数单个参数的情况是否省略括号,默认always是总是带括号(arrowParens: "<always|avoid>")

arrowParens: \'always\',

// 11.range是format执行的范围,可以选执行一个文件的一部分,默认的设置是整个文件(rangeStart: <int> rangeEnd: <int>)

rangeStart: 0,

rangeEnd: Infinity,

// 12. requirePragma: <bool>,格式化有特定开头编译指示的文件 比如下面两种

/**

* @prettier

*/

// or

/**

* @format

*/

requirePragma: false,

// 13.insertPragma: <bool> 自动插入pragma到已经完成的format的文件开头

insertPragma: false,

// 14. proseWrap: "<always|never|preserve>" 文章换行,默认情况下会对你的markdown文件换行 进行format会控制在printwidth以内

proseWrap: \'always\',

// 15. htmlWhitespaceSensitivity: "<css|strict|ignore>" html中的空格敏感性

// html文档片段 1<b>2</b>3 原本显示为123, 不设置忽略空格的话格式化后会变成 1<b> 2 </b>3 显示为1 2 3

htmlWhitespaceSensitivity: \'ignore\',

// 16. vue script和style标签中是否缩进,开启可能会破坏编辑器的代码折叠

vueIndentScriptAndStyle: false,

// 17. endOfLine: "<lf|crlf|cr|auto>" 行尾换行符,默认是lf,

endOfLine: \'lf\',

// 18. 控制被引号包裹的代码是否进行格式化, 默认是auto,

embeddedLanguageFormatting: \'off\'

}

4 配置移动端UI库

做移动端开发,虽然定制性比较强。绝大多数UI库组件都用不到,但像Toast,Modal,Picker,Form,PullRefresh等组件几乎是必用,所以需要引入移动端UI库。

vue3移动端UI库的选择:

antd-mobile-vue-next移入项目之后,编译报错
VuxUI风格是绿色系,与现有项目使用的蓝色系风格UI不符,  所以没用
Vant是业界主流的移动端组件库之一,UI色系风格与历史项目相符,支持vue3,组件功能优于Vux,已Toast为例,Vant提供了网络加载的Toast, Vux未提供。Vant总共提供了69个(不含组合api)涵盖基础,表单,反馈,展示,导航,业务六大类组件。

 yarn add vant@3

按需引入

按需加载需要借助babel-plugin-import, 这样就可以只引入需要的组件,以减小项目体积

yarn add babel-plugin-import -D

 对babel.config.js进行配置

module.exports = {

presets: ["@vue/cli-plugin-babel/preset"],

plugins: [

[

"import",

{

libraryName: "vant",

libraryDirectory: "es",

style: true,

},

"vant",

],

],

};

 main.js中引入vant的样式

import { createApp } from "vue";

import App from "./App.vue";

import "vant/lib/index.css";

createApp(App).mount("#app");

在App.vue中引入组件

<template>

<div>

<Button type="primary">主要按钮</Button>

<img alt="Vue logo" src="./assets/logo.png" />

<HelloWorld msg="Welcome to Your Vue.js App" />

</div>

</template>

<script>

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

import { Button } from "vant";

export default {

name: "App",

components: {

HelloWorld,

Button,

},

};

</script>

 5 配置开发环境请求代理

请求代理是解决本地开发请求跨域的最佳方式之一,对前后端代码都没有侵入性。  在vue.config.js中添加代理转发配置:

const { defineConfig } = require("@vue/cli-service");

module.exports = defineConfig({

transpileDependencies: true,

devServer: {

port: 9000,

host: "localhost",

https: false,

open: "/",

proxy: {

"/api": {

target: "http://192.168.xx.xx:50000",

secure: false,

changeOrigin: true,

logLevel: "debug",

},

},

},

// ....

});

6 配置路径别名

项目统一使用路径别名,好处是在代码中不用写../../../之类让人看着有些云里雾里的文件引用路径,此外用短路径替代长路径,书写也更方便。而且编辑器对于别名路径也有提示,可以跳转。

需要注意的是,如果使用了TypeScript,除了要在vue.config.js中配置路径别名之外,还需要在tsconfig.json配置路径别名,否则虽然打包编译不报错,但是代码编辑器却会提示引用路径有错误。

vue.config.js路径别名配置

const path = require(\'path\');

module.exports = {

configureWebpack: {

resolve: {

alias: {

\'@\': path.join(__dirname, \'src/\')

}

}

}

}

 tsconfig.json路径别名配置

{

"compilerOptions": {

// ...

"baseUrl": ".",

"paths": {

"@/*": ["src/*"],

}

},

"include": [

"src/**/*.ts",

"src/**/*.tsx",

"src/**/*.vue",

// 包含自定义声明文件

"typings/**/*.d.ts",

],

// ...

}

7 设置自定义环境变量

开发调试的时候,需要动态在命令行添加动态参数,用以执行开发环境的调试逻辑,将自定义的命令行参数传到业务文件的方法是:

在package.json中传入自定义环境变量

{

// ...

"scripts": {

"start:wx": "ytt && vue-cli-service serve --mode local --wx true",

// ...

},

}

在vue.config.js中设置自定义环境变量

// ...

const webpack = require(\'webpack\');

const { defineConfig } = require(\'@vue/cli-service\');

const { wx, mode } = require(\'minimist\')(process.argv.slice(2));

console.log({ wx, mode });

// console.log(process.env.VITE_API_HOST);

module.exports = defineConfig({

// ...

configureWebpack: {

plugins: [

// 定义环境变量

new webpack.DefinePlugin({

\'process.env.WX_JS_SDK_ENABLED\': wx, // 是否真机调试SDK模式

\'process.env.CURRENT_ENV\': JSON.stringify(mode),

}),

],

},

});

在业务文件中接收自定义环境变量

import { createApp } from \'vue\';

import \'vant/lib/index.css\';

import App from \'./App.vue\';

import router from \'./router\';

import store from \'./store\';

console.log(process.env.WX_JS_SDK_ENABLED, process.env.CURRENT_ENV);

createApp(App).use(store).use(router).mount(\'#app\');

8 配置stylelint校验规则

stylelint的好处:

  • 可以发现样式书写问题,如无效的十六进制值;重复的选择器;未命名的动画名称;错误的线性渐变语法;后面的属性覆盖前面的属性;前面的选择器优先级更高,覆盖后面的属性;选择器下未设置任何属性等。
  • 能使所有人写的样式风格都一致,按照业内知名公司 (GitHub、Google、Airbnb)的样式规范要求写样式。
  • 保存时自动对样式书写进行优化(如采用样式的简写形式,删除无意义小数点前面的0,调整样式顺序等),修复可以修复的样式错误。

1.安装依赖

yarn  add -D stylelint stylelint-config-recess-order  stylelint-order stylelint-config-standard stylelint-less  stylelint-webpack-plugin postcss-html

2. 创建.stylelintrc.js 样式校验规则

module.exports = {

plugins: [\'stylelint-less\'],

extends: [\'stylelint-order\', \'stylelint-config-standard\', \'stylelint-config-recess-order\'],

rules: {

indentation: 2,

\'at-rule-no-unknown\': [true, { ignoreAtRules: [\'mixin\', \'extend\', \'content\', \'include\'] }],

\'no-empty-source\': null, // null是关闭规则的意思--less文件内容可以为空

\'no-descending-specificity\': null, //禁止特异性较低的选择器在特异性较高的选择器之后重写

\'font-family-no-missing-generic-family-keyword\': null, // 关闭必须设置通用字体的规则

\'property-no-unknown\': [

true,

{

ignoreProperties: [\'box-flex\'], // 忽略某些未知属性的检测

},

],

\'selector-pseudo-element-no-unknown\': [

true,

{

ignorePseudoElements: [\'ng-deep\'], // 忽略ng-deep这种合法的伪元素选择器报警

},

],

\'declaration-colon-newline-after\': null, //一个属性过长的话可以写成多行

\'media-feature-name-no-unknown\': null, // 关闭禁止未知的媒体功能名

// 下面的排序规则是stylelint-config-recess-order的css排序规则,

// 要对某个属性排序进行调整,这个属性之前的样式排序都要配置在自定义属性排序中

\'order/properties-order\': [

{

// Must be first.

properties: [\'all\'],

},

{

// Position.

properties: [\'position\', \'top\', \'right\', \'bottom\', \'left\', \'z-index\'],

},

{

// Display mode.

properties: [\'box-sizing\', \'display\'],

},

{

// Flexible boxes.

properties: [\'flex\', \'flex-basis\', \'flex-direction\', \'flex-flow\', \'flex-grow\', \'flex-shrink\', \'flex-wrap\'],

},

{

// Grid layout.

properties: [

\'grid\',

\'grid-area\',

\'grid-template\',

\'grid-template-areas\',

\'grid-template-rows\',

\'grid-template-columns\',

\'grid-row\',

\'grid-row-start\',

\'grid-row-end\',

\'grid-column\',

\'grid-column-start\',

\'grid-column-end\',

\'grid-auto-rows\',

\'grid-auto-columns\',

\'grid-auto-flow\',

\'grid-gap\',

\'grid-row-gap\',

\'grid-column-gap\',

],

},

{

// Align.

properties: [\'align-content\', \'align-items\', \'align-self\'],

},

{

// Justify.

properties: [\'justify-content\', \'justify-items\', \'justify-self\'],

},

{

// Order.

properties: [\'order\'],

},

{

// Box model.

properties: [

\'float\',

\'width\',

\'min-width\',

\'max-width\',

\'height\',

\'line-height\',

\'min-height\',

\'max-height\',

\'padding\',

\'padding-top\',

\'padding-right\',

\'padding-bottom\',

\'padding-left\',

\'margin\',

\'margin-top\',

\'margin-right\',

\'margin-bottom\',

\'margin-left\',

\'overflow\',

\'overflow-x\',

\'overflow-y\',

\'-webkit-overflow-scrolling\',

\'-ms-overflow-x\',

\'-ms-overflow-y\',

\'-ms-overflow-style\',

\'clip\',

\'clear\',

],

},

{

// Typography.

properties: [

\'font\',

\'font-family\',

\'font-size\',

\'font-style\',

\'font-weight\',

\'font-variant\',

\'font-size-adjust\',

\'font-stretch\',

\'font-effect\',

\'font-emphasize\',

\'font-emphasize-position\',

\'font-emphasize-style\',

\'-webkit-font-smoothing\',

\'-moz-osx-font-smoothing\',

\'font-smooth\',

\'hyphens\',

\'color\',

\'text-align\',

\'text-align-last\',

\'text-emphasis\',

\'text-emphasis-color\',

\'text-emphasis-style\',

\'text-emphasis-position\',

\'text-decoration\',

\'text-indent\',

\'text-justify\',

\'text-outline\',

\'-ms-text-overflow\',

\'text-overflow\',

\'text-overflow-ellipsis\',

\'text-overflow-mode\',

\'text-shadow\',

\'text-transform\',

\'text-wrap\',

\'-webkit-text-size-adjust\',

\'-ms-text-size-adjust\',

\'letter-spacing\',

\'word-break\',

\'word-spacing\',

\'word-wrap\', // Legacy name for `overflow-wrap`

\'overflow-wrap\',

\'tab-size\',

\'white-space\',

\'vertical-align\',

\'list-style\',

\'list-style-position\',

\'list-style-type\',

\'list-style-image\',

],

},

{

// Accessibility & Interactions.

properties: [

\'pointer-events\',

\'-ms-touch-action\',

\'touch-action\',

\'cursor\',

\'visibility\',

\'zoom\',

\'table-layout\',

\'empty-cells\',

\'caption-side\',

\'border-spacing\',

\'border-collapse\',

\'content\',

\'quotes\',

\'counter-reset\',

\'counter-increment\',

\'resize\',

\'user-select\',

\'nav-index\',

\'nav-up\',

\'nav-right\',

\'nav-down\',

\'nav-left\',

],

},

{

// Background & Borders.

properties: [

\'background\',

\'background-color\',

\'background-image\',

"-ms-filter:\\\'progid:DXImageTransform.Microsoft.gradient",

\'filter:progid:DXImageTransform.Microsoft.gradient\',

\'filter:progid:DXImageTransform.Microsoft.AlphaImageLoader\',

\'filter\',

\'background-repeat\',

\'background-attachment\',

\'background-position\',

\'background-position-x\',

\'background-position-y\',

\'background-clip\',

\'background-origin\',

\'background-size\',

\'background-blend-mode\',

\'isolation\',

\'border\',

\'border-color\',

\'border-style\',

\'border-width\',

\'border-top\',

\'border-top-color\',

\'border-top-style\',

\'border-top-width\',

\'border-right\',

\'border-right-color\',

\'border-right-style\',

\'border-right-width\',

\'border-bottom\',

\'border-bottom-color\',

\'border-bottom-style\',

\'border-bottom-width\',

\'border-left\',

\'border-left-color\',

\'border-left-style\',

\'border-left-width\',

\'border-radius\',

\'border-top-left-radius\',

\'border-top-right-radius\',

\'border-bottom-right-radius\',

\'border-bottom-left-radius\',

\'border-image\',

\'border-image-source\',

\'border-image-slice\',

\'border-image-width\',

\'border-image-outset\',

\'border-image-repeat\',

\'outline\',

\'outline-width\',

\'outline-style\',

\'outline-color\',

\'outline-offset\',

\'box-shadow\',

\'mix-blend-mode\',

\'filter:progid:DXImageTransform.Microsoft.Alpha(Opacity\',

"-ms-filter:\\\'progid:DXImageTransform.Microsoft.Alpha",

\'opacity\',

\'-ms-interpolation-mode\',

],

},

{

// SVG Presentation Attributes.

properties: [

\'alignment-baseline\',

\'baseline-shift\',

\'dominant-baseline\',

\'text-anchor\',

\'word-spacing\',

\'writing-mode\',

\'fill\',

\'fill-opacity\',

\'fill-rule\',

\'stroke\',

\'stroke-dasharray\',

\'stroke-dashoffset\',

\'stroke-linecap\',

\'stroke-linejoin\',

\'stroke-miterlimit\',

\'stroke-opacity\',

\'stroke-width\',

\'color-interpolation\',

\'color-interpolation-filters\',

\'color-profile\',

\'color-rendering\',

\'flood-color\',

\'flood-opacity\',

\'image-rendering\',

\'lighting-color\',

\'marker-start\',

\'marker-mid\',

\'marker-end\',

\'mask\',

\'shape-rendering\',

\'stop-color\',

\'stop-opacity\',

],

},

{

// Transitions & Animation.

properties: [

\'transition\',

\'transition-delay\',

\'transition-timing-function\',

\'transition-duration\',

\'transition-property\',

\'transform\',

\'transform-origin\',

\'animation\',

\'animation-name\',

\'animation-duration\',

\'animation-play-state\',

\'animation-timing-function\',

\'animation-delay\',

\'animation-iteration-count\',

\'animation-direction\',

],

},

],

},

};

编译时自动修复

// ...

const { defineConfig } = require(\'@vue/cli-service\');

const StylelintPlugin = require(\'stylelint-webpack-plugin\');

module.exports = defineConfig({

// ...

configureWebpack: {

plugins: [

// ...

new StylelintPlugin({

files: [\'src/**/*.vue\'],

// 编译时自动修复

fix: true,

// 这样配才能修复vue文件style片段中的less语法

customSyntax: \'postcss-html\',

}),

],

},

});

安装VSCode stylelint扩展

在.vscode/settings.json中配置保存代码时自动修复样式错误

{

"editor.codeActionsOnSave": {

// ...

"source.fixAll.stylelint": true

},

// 关闭vscode自带的css,less,scss报错提示

"css.validate": false,

"less.validate": false,

"scss.validate": false,

"stylelint.validate": ["css", "less"]

}

9 配置yapi-to-typescript

typescript面世以来,经历了一个从厌烦到喜欢的过程,厌恶的是要在原来开发的基础上,多做一些繁杂数据类型定义的工作,喜欢的是确实帮助开发者发现了许多语法错误,享受到接口和传参的便利提示, 综合起来,还是利大于弊,所以 越来越多的开发者开始加入ts大家庭。yapi-to-typescript这个工具,可以帮我们省去接口数据类型定义的工作量。让我们更愉快的与ts玩耍。

安装依赖

yarn add -D yapi-to-typescript

创建ytt.config.ts配置文件

import { defineConfig } from \'yapi-to-typescript\';

/**

* 生成Api接口名称 Interface和ChangeCase数据类型参见node_modules\yapi-to-typescript\lib\esm\index.d.ts定义

* @param interfaceInfo : Interface

* @param changeCase:ChangeCase

* @returns 请求响应接口名称--pascal命名

*/

function genApiInterfaceName(interfaceInfo, changeCase) {

// 取解析路径dir最尾部的路径作为前缀路径

const lastPath = interfaceInfo.parsedPath.dir.split(\'/\').pop();

// 拼接前缀路径+文件名称

return `${changeCase.pascalCase(lastPath)}${changeCase.pascalCase(interfaceInfo.parsedPath.name)}`;

}

export default defineConfig([

{

serverUrl: \'https://yapi.xxx.com\',

typesOnly: true,

target: \'typescript\',

reactHooks: {

enabled: false,

},

prodEnvName: \'项目名称\',

// 将生成文件路径转化成小驼峰命名方式

outputFilePath: (interfaceInfo, changeCase) => {

// 文件夹名称取api-url路径末尾2个

const filePathArr = interfaceInfo.path.split(\'/\').slice(-2);

const filePath = filePathArr.map((item) => changeCase.camelCase(item)).join(\'/\');

return `typings/httpTypes/${filePath}.ts`;

},

// 生成ts文件中请求参数interface名称,将下划线命名转换成pascal命名

getRequestDataTypeName: (interfaceInfo, changeCase) => {

return `${genApiInterfaceName(interfaceInfo, changeCase)}Request`;

},

// 生成ts文件中请求响应数据interface名称,将下划线命名转换成pascal命名

getResponseDataTypeName: (interfaceInfo, changeCase) => {

return `${genApiInterfaceName(interfaceInfo, changeCase)}Response`;

},

// 响应数据中要生成ts数据类型的键名

dataKey: \'retdata\',

projects: [

{

// token获取方式: 在yapi-设置-token配置中查看

token: \'xxx\',

// 分类id查找方式: 点击接口左侧的分类菜单,查看url地址栏最后面的数字获取

// 分类id配置特别重要,配置错了无法生成对应的ts数据类型定义文件

categories: [

{

id: [xxx], // 民生立减金API分类id

},

],

},

],

},

]);

3.在package.json中配置ytt指令

{

// ...

"scripts": {

"start": "ytt && vue-cli-service serve --mode local",

"build": "ytt && vue-cli-service build --mode local",

"ytt": "ytt",

},

}

4.在.gitignore中添加对httpTypes下文件的忽略

# ...

/typings/httpTypes/*

# ...

10 配置commitlint

commit message 是程序员开发的日常高频操作,自然状态下commit message 呈现五花八门的书写风格,不利于阅读和维护,规范的 commit message 有助于团队做 code review, 输出清晰明了的 CHANGELOG, 有利于项目的长期维护。

安装依赖包

yarn add -D husky conventional-changelog-cli @commitlint/{cli,config-conventional}

创建提交校验配置文件commitlint.config.js

/**

* git commit最佳实践

* 1.经常commit,One Thing,One Commit

* 2.commit之前测试,不要commit一半工作;

* 3.编写规范的commit message

*/

/**

* Commit message 包括三个部分:Header,Body 和 Footer

* <type>(<scope>): <subject>

* 空一行

* <body>

* 空一行

* <footer>

*/

module.exports = {

extends: [\'@commitlint/config-conventional\'],

rules: {

// Header包括三个字段:type(必需)、scope(可选)和subject(必需)。最多200字

\'header-max-length\': [2, \'always\', 200],

// 提交类型<type>枚举

\'type-enum\': [

2,

\'always\',

[

\'init\', // 项目初始化

\'clean\', // 清理过时无用文件

\'merge\', // 合并代码

\'style\', // 修改样式文件(包括css/less/sass,图片,字体文件)

\'format\', // 格式化,不影响代码含义的修改,比如空格、格式缩进、缺失的分号等

\'build\', // 改变构建流程、或者增加依赖库、工具等 如webpack.config.js,package.json yarn.lock

\'chore\', // 各种配置文件的修改, 如.gitignore,tsconfig.json,.vscode,.tenone, eslint/stylelint,envConfig

\'ci\', // 对CI配置文件或脚本进行了修改

\'docs\', // 修改项目说明文档

\'feat\', // 新增功能

\'fix\', // 修复bug

\'perf\', // 性能优化

\'refactor\', // 既不是修复bug也不是添加功能的代码重构

\'revert\', // 版本回退

\'test\', // 修改测试用例

],

],

// 格式-可选值

// \'lower-case\' 小写 lowercase

// \'upper-case\' 大写 UPPERCASE

// \'camel-case\' 小驼峰 camelCase

// \'kebab-case\' 短横线 kebab-case

// \'pascal-case\' 大驼峰 PascalCase

// \'sentence-case\' 首字母大写 Sentence case

// \'snake-case\' 下划线 snake_case

// \'start-case\' 所有首字母大写 start-case

// <type> 不能为空

\'type-empty\': [2, \'never\'],

// <type> 格式 小写

\'type-case\': [2, \'always\', \'lower-case\'],

// <scope> 关闭改动范围不能为空规则

\'scope-empty\': [0, \'never\'],

// <scope> 格式 小写

\'scope-case\': [2, \'always\', \'lower-case\'],

// <subject> 不能为空

\'subject-empty\': [2, \'never\'],

// <subject> 关闭 以.为结束标志

\'subject-full-stop\': [0, \'never\', \'.\'],

// <subject> 格式

\'subject-case\': [2, \'never\', []],

// <body> 以空行开头

\'body-leading-blank\': [1, \'always\'],

// <footer> 以空行开头

\'footer-leading-blank\': [1, \'always\'],

},

};

3. 创建提交校验shell脚本 husky.sh和commit-msg

yarn husky install

在.husky文件夹下创建commit-msg文件

npx husky add .husky/commit-msg

在.husky/commit-msg文件中写入

#!/bin/sh

. "$(dirname "$0")/_/husky.sh"

# 提交记录检查

yarn commitlint --edit $1

# 代码重复率检测

yarn jscpd

# 格式化检查

yarn format:check

# eslint检查

yarn lint:check

11 配置代码重复率检测工具jscpd

代码的简洁之道有一条铁律是 Don\'t Repeat Yourself,那么如何快速地检测出项目出是否存在着大段的重复代码,靠人工检查显然不可取,这种重复体力活应该交给工具。

检测前端代码重复率的工具有jsinspect、jscpd,PMD-CPD(PMD\'s Copy/Paste Detector)

  • jsinspect工具支持js和jsx格式的文件,基于抽象语法树,可以检测出结构类似的代码块
  • PMD-CPD工具支持js文件检测,也可以自己开发扩展包来解析指定的语言
  • jscpd工具支持文件格式广泛,如js、jsx、vue、ts、less,java、oc等。其重复率判定依据为一定长度标识符的MD5值是否相同

每个工具各有其优缺点,若只需要检测js或jsx文件,且对检测结果要求较高,可以选择jsinspect或者PMD-CPD工具,若考虑检测工具的通用性,可以选择jscpd工具。

安装:

npm install -g jscpd

用法:

jscpd  src/*

在项目下创建.jscpd.json配置文件

{ 
// 重复率阈值

"threshold": 0.1,
// 报告输出格式

"reporters": [

"html",

"console"

],

"ignore": [

"dist/**",

"node_modules/**"

],
// 文件路径使用相对路径

"absolute": false

}

 --min-tokens -k:代码的最小块大小。小于的代码块min-tokens将被跳过,默认为50;
 --min-lines -l:最小代码行数,默认为5;
 --max-lines -x: 最大代码行数,默认为1000;
 --max-size -z:最大文件大小,单位为kb,默认100;
 --threshold -t:重复级别的阈值,当项目重复级别大于该阈值时报错退出,默认为空;
 --ignore -i:忽略的文件类型;
 --reporters -r:输出类型



参考文献

  • Vue3+TS,写一个逼格满满的项目

  • Vue3,我决定不再使用Vuex

  • vue.config.js配置项
  • prettier使用指南(包含所有配置项)

  • vue3 composition(组合式)API 是什么?我为什么要使用它?

  • 检测前端代码重复率工具

  • Vue 3 生命周期完整指南

  • Ant Design Pro Vue 
  • [try-catch优雅写法]

以上是 你在寻找Vue3移动端项目框架嘛?请看这里 的全部内容, 来源链接: utcz.com/z/376669.html

回到顶部