####安装
通过 npm
npm install -g pnpm
升级
pnpm add -g pnpm
命令行
npm 命令 | pnpm 等效 |
---|---|
npm install |
pnpm install |
npm i <pkg> |
[pnpm add <pkg> ] |
npm run <cmd> |
[pnpm <cmd> ] |
1.开源复合组件不要破坏性的更改
问题 | 解决方案 | |
---|---|---|
nodejs 版本不匹配 | nodejs 统一使用 v16.13.0,开发环境包管理器统一使用 pnpm | |
multipleTab 关闭时无法缓存路由 | 手动在页面路由回调中调用 tabStore 的 action 将该页面加入缓存列表 | |
svg 图标存在底色 | svg 分文件中将带有色值的 fill 属性的属性值修改为 currentColor | |
vue watch 无法监听数据变动 | 配置属性 {deep:true} | |
开发中页面刷新 | 观察控制台,是否出现 vite 相关依赖更新,刷新页面 vite dependencies updated reloading page ,将该依赖加入 main.ts 的对是否 dev 环境的判断中 |
|
文件夹大小写重命名 | 出现重名文件夹只修改大小写的情况时应使用git mv casesensitive tmp 再git mv tmp CaseSensitive |
相关 |
debugger 行数不准确 | chrome devtool-setting-workspace 将当前项目添加到工作区中 |
组件 | 改动 | |
---|---|---|
ApiSelect | valueField 为'gke-JSON'时选项值为整个对象 | |
BasicModal | title:false 隐藏头部 | |
BasicForm | emits 新加@getSearchForm 方法 |
项目路由配置存放于 src/router/routes
下面。 src/router/routes/modules
用于存放路由模块,在该目录下的文件会自动注册。
在 src/router/routes/modules
内的 .ts 文件会被视为一个路由模块。其中 Meta 配置项说明
以结果管理示例
import type { AppRouteModule } from '/@/router/types';
import { LAYOUT } from '/@/router/constant';
const resultRoute: AppRouteModule = {
path: '/resultManagement',
name: 'resultManagement',
component: LAYOUT,
redirect: '/resultManagement/resultList',
meta: {
title: '结果管理',
hideChildrenInMenu: false,
icon: '结果管理|svg',
pid: 0,
orderNo: 30,
id: 3,
},
children: [
{
path: 'resultList',
name: 'ResultList',
component: () => import('/@/views/resultManagement/resultList/index.vue'),
meta: {
hideBreadcrumb: true,
title: '样本清单',
// currentActiveMenu: '/dashboard',
icon: '样本列表|svg',
id: 14,
},
},
],
};
export default resultRoute;
meta
中的 id
对应后端数据库菜单 id
,用于对应前端路由,一旦后端修改,前端需对应修改。
开启缓存有 3 个条件
- 在 src/settings/projectSetting.ts 内将
openKeepAlive
设置为true
- 路由设置
name
,且不能重复 - 路由对应的组件加上
name
,与路由设置的name
保持一致
关闭某页面缓存
router.meta
下配置
export interface RouteMeta {
// 是否忽略KeepAlive缓存
ignoreKeepAlive?: boolean;
}
src\settings\projectSetting.ts
中 permissionMode
路由模式设为 PermissionModeEnum.ROUTE_MAPPING
前端路由时,路由会自动转换成左侧菜单。不需要转换的路由在 meta
中单独设置 hideMenu: false
。
接口统一存放于 src/api/
下面管理
实例:
import { defHttp } from '/@/utils/http/axios';
import { LoginParams, LoginResultModel } from './model/userModel';
enum Api {
Login = '/login',
}
export function loginApi(params: LoginParams) {
return defHttp.request<LoginResultModel>({
url: Api.Login,
method: 'POST',
params,
});
}
axios
统一返回处理和代理封装 src\utils\http\axios\index.ts
实例:
export const stampHttp = createAxios({
requestOptions: {
apiUrl: '/stamp-api',
urlPrefix: '',
},
});
环境配置文件 .env
中
VITE_PROXY = [["/stamp-api","http://192.168.12.1:15014"]]
默认使用 less 作为预处理语言,项目中使用的通用样式,都存放于 src/design/ 下面。
.
├── ant # ant design 一些样式覆盖
├── color.less # 颜色
├── index.less # 入口
├── public.less # 公共类
├── theme.less # 主题相关
├── config.less # 每个组件都会自动引入样式
├── transition # 动画相关
└── var # 变量
全局注入
config.less 这个文件会被全局注入到所有文件
项目中引用到了 tailwindcss, 具体可以见文件使用说明。
语法如下:
<div class="relative w-full h-full px-4"></div>
使用 scoped 后,父组件的样式将不会渗透到子组件中,使用以下方式解决
<style scoped>
/* 深度选择器 (已弃用) */
::v-deep(.foo) {
}
/* 缩写 (推荐) */
:deep(.foo) {
}
/* targeting slot content */
::v-slotted(.foo) {
}
/* shorthand */
:slotted(.foo) {
}
/* one-off global rule */
::v-global(.foo) {
}
/* shorthand */
:global(.foo) {
}
</style>
优势:
- 更少的样板内容,更简洁的代码。
- 能够使用纯 Typescript 声明 props 和抛出事件。
- 更好的运行时性能 (其模板会被编译成与其同一作用域的渲染函数,没有任何的中间代理)。
- 更好的 IDE 类型推断性能 (减少语言服务器从代码中抽离类型的工作)。
<script setup>
console.log('hello script setup');
</script>
当使用 <script setup>
的时候,任何在 <script setup>
声明的顶层的绑定 (包括变量,函数声明,以及 import 引入的内容) 都能在模板中直接使用:
<script setup>
// 变量
const msg = 'Hello!';
// 函数
function log() {
console.log(msg);
}
</script>
<template>
<div @click="log">{{ msg }}</div>
</template>
import 导入的内容也会以同样的方式暴露。意味着可以在模板表达式中直接使用导入的 helper 函数,并不需要通过 methods
选项来暴露它:
<script setup>
import { capitalize } from './helpers';
</script>
<template>
<div>{{ capitalize('hello') }}</div>
</template>
可以使用带点的组件标记,例如 <Foo.Bar>
来引用嵌套在对象属性中的组件。这在需要从单个文件中导入多个组件的时候非常有用:
<script setup>
import * as Form from './form-components';
</script>
<template>
<Form.Input>
<Form.Label>label</Form.Label>
</Form.Input>
</template>
在 <script setup>
中必须使用 defineProps
和 defineEmits
API 来声明 props
和 emits
,它们具备完整的类型推断并且在 <script setup>
中是直接可用的:
<script setup>
const props = defineProps({
foo: String,
});
const emit = defineEmits(['change', 'delete']);
// setup code
</script>
defineProps
和defineEmits
都是只在<script setup>
中才能使用的编译器宏。他们不需要导入且会随着<script setup>
处理过程一同被编译掉。defineProps
接收与props
选项相同的值,defineEmits
也接收emits
选项相同的值。defineProps
和defineEmits
在选项传入后,会提供恰当的类型推断。- 传入到
defineProps
和defineEmits
的选项会从 setup 中提升到模块的范围。因此,传入的选项不能引用在 setup 范围中声明的局部变量。这样做会引起编译错误。但是,它可以引用导入的绑定,因为它们也在模块范围内。
<script setup>
可以和 <script>
一起使用
- 无法在
<script setup>
声明的选项,例如inheritAttrs
或通过插件启用的自定义的选项。 - 声明命名导出。
- 运行副作用或者创建只需要执行一次的对象。
<script>
// 普通 <script>, 在模块范围下执行(只执行一次)
runSideEffectOnce();
// 声明额外的选项
export default {
name: 'ComponentName',
inheritAttrs: false,
customOptions: {},
};
</script>
<script setup>
// 在 setup() 作用域中执行 (对每个实例皆如此)
</script>
组件名应该始终由多个单词组成,除了根组件 App
,以及 <transition>
、<component>
之类的 Vue 内置组件。
这样做可以避免与现有以及未来的 HTML 元素产生冲突,因为所有的 HTML 元素名称都是单个单词的。
Prop 定义应尽量详细
在提交的代码中,prop 的定义应该尽量详细,至少指定其类型。
-
feat
增加新功能fix
修复问题/BUGstyle
代码风格相关无影响运行结果的perf
优化/性能提升refactor
重构revert
撤销修改test
测试相关docs
文档/注释chore
依赖更新/脚手架配置修改等workflow
工作流改进ci
持续集成types
类型定义文件更改wip
开发中
src -- 源码目录
├── api -- axios网络请求定义
├── assets -- 静态资源
├── constant -- 常量(sdk配置信息,枚举)
├── enums --枚举
├── locales --语言
├── router -- 路由
├── store -- 状态
├── design --通用样式
├── components -- 通用组件
├── directives --通用指令
├── logics --应用级逻辑
├── hooks --通用逻辑作用类似于vue2中的mixin技术
├── utils -- 工具类
├── settings -- 配置
└── views -- 前端页面
├── home -- 首页
├── sys --系统级
-
对齐原则(页面组件内容左对齐,表格字段居中对齐,dialog 垂直居中)
-
滚动区域原则 (1 组件中存在表格的,首先禁止滚动条 ,设置表格内容区域可滚动,最后自适应表格高度)
- 下拉选择框默认携带全部选项
- 删除操作需要二次弹窗,按钮需要加 loading
- 行内表单第一项 lableWith="auto" (多行对齐?)
- dialog 禁止设置高度
- 增删改后刷新列表
- modal 关闭取消后重置表单
- 按钮触发 api 的 加上 loading 机制(useThrottleFn,useDebounceFn)
- 虚拟滚动组件