1.可编辑,针对现在一些需要绑定才可以复制的文章,还原就是刷新当前页面
javascript:document.body.contentEditable=true
2.常见的比较好用的vscode插件
名字 | 作用 | 快捷键 |
---|---|---|
Auto Rename Tag | 创建元素,子元素会跟着复制 | |
Chinese (Simplified) | 简化中文 | |
Code Runner | 本地调试, | |
ESLint | 比较基础的代码检查,(较为麻烦,规范多) | |
GitLens | git代码可视化工具,必备 | |
Image preview | 图片预览 | |
javascript console utils | 用来简化log,选中然后快捷键 | Cmd+Shift+L:创建,Cmd+Shift+D:删除 |
koroFileHeader | 页面头部标签,可以规范当前页面是谁开发,确定是经常这边起冲突 | 需要简单配置 |
New Relic CodeStream | 代码审核, |
名字 | 作用 | 快捷键 |
---|---|---|
Open In Default Browse | 打开默认的浏览器 | 稍微长一点的文本 |
Prettier - Code formatter | 检查(比较好) | |
Simple React Snippets | react的代码补充提示 | |
Stylelint | css的格式 | |
Todo Tree | 未完待续 | //TODO |
Debugger for Chrome | 调试代码 | |
Svg Preview | 可编辑svg | |
JavaScript (ES6) code snippets | 一些缩写,有一些是自带 | |
//setting.json
{
"editor.codeActionsOnSave": {
"source.fixAll.stylelint": true
},
"fileheader.customMade": {
"Author": "**",
"Date": "Do not edit",
"LastEditors": "**",
"LastEditTime": "Do not edit",
"Description": "file contents"
},
"[typescriptreact]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[javascript]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[typescript]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"editor.tabSize": 2,
"explorer.confirmDragAndDrop": false,
"editor.guides.bracketPairs": true,
"editor.bracketPairColorization.enabled": true,
"git.confirmSync": false,
"editor.formatOnSave": true,
"editor.defaultFormatter": "esbenp.prettier-vscode",
"eslint.packageManager": "yarn",
"workbench.editor.enablePreview": false,
"codestream.email": "2667476189@qq.com",
"codestream.showAvatars": false,
"editor.linkedEditing": true,
"gitlens.gitCommands.skipConfirmations": [
"fetch:command",
"switch:command",
"stash-push:command"
],
"emmet.showSuggestionsAsSnippets": true,
"lit-html.format.enabled": false,
"editor.snippetSuggestions": "top",
"codestream.serverUrl": "https://api.codestream.com",
"emmet.preferences": {},
"editor.formatOnType": true,
"editor.formatOnSave": true,
"fileheader.configObj": {
"createFileTime": true,
"language": {
"languagetest": {
"head": "/$$",
"middle": " $ @",
"end": " $/",
"functionSymbol": {
"head": "/** ",
"middle": " * @",
"end": " */"
},
"functionParams": "js"
}
},
"autoAdd": true,
"autoAddLine": 100,
"autoAlready": true,
"annotationStr": {
"head": "/*",
"middle": " * @",
"end": " */",
"use": false
},
"headInsertLine": {
"php": 2,
"sh": 2
},
"beforeAnnotation": {
"文件后缀": "该文件后缀的头部注释之前添加某些内容"
},
"afterAnnotation": {
"文件后缀": "该文件后缀的头部注释之后添加某些内容"
},
"specialOptions": {
"特殊字段": "自定义比如LastEditTime/LastEditors"
},
"switch": {
"newlineAddAnnotation": true
},
"supportAutoLanguage": [],
"prohibitAutoAdd": ["json"],
"folderBlacklist": ["node_modules", "文件夹禁止自动添加头部注释"],
"prohibitItemAutoAdd": [
"项目的全称, 整个项目禁止自动添加头部注释, 可以使用快捷键添加"
],
"moveCursor": true,
"dateFormat": "YYYY-MM-DD HH:mm:ss",
"atSymbol": ["@", "@"],
"atSymbolObj": {
"文件后缀": ["头部注释@符号", "函数注释@符号"]
},
"colon": [": ", ": "],
"colonObj": {
"文件后缀": ["头部注释冒号", "函数注释冒号"]
},
"filePathColon": "路径分隔符替换",
"showErrorMessage": false,
"writeLog": false,
"wideSame": false,
"wideNum": 13,
"functionWideNum": 0,
"CheckFileChange": false,
"createHeader": true,
"useWorker": false,
"designAddHead": false,
"headDesignName": "random",
"headDesign": false,
"cursorModeInternalAll": {},
"openFunctionParamsCheck": true,
"functionParamsShape": ["{", "}"],
"functionBlankSpaceAll": {},
"functionTypeSymbol": "*",
"typeParamOrder": "type param",
"customHasHeadEnd": {},
"throttleTime": 60000
},
"settingsSync.ignoredExtensions": [],
"settingsSync.ignoredSettings": [],
"git.mergeEditor": false,
"workbench.colorTheme": "Default Dark+",
"window.zoomLevel": 3
}
-
统一使用 yarn 管理依赖
-
务必安装好 vscode 插件 eslint、styleLint、prettier
-
仅使用函数组件(除极为特殊的一定需要使用 class 组件的情况)
-
每个文件只存在一个 react 组件(可以存在多个无状态组件)
-
使用空格进行缩紧,一个制表符的宽度为 2 个空格
-
定义对象类型使用 interface 定义;定义字面量集合使用 type 定义;定义多个类型的合并使用 type+交叉类型(组合);
-
原则上不允许使用 /_ disable _/ 的形式绕过 eslint 检查,如果实在需要绕过检查,同一文件内最多出现一处,操作方法如下:
单行: // eslint-disable-next-line 多行: /* eslint-disabel */ /* eslint-enable */ 整个文件(文件顶部声明): /* eslint-disable */
-
类型定义尽可能的使用 sdk 的类型定义
-
组件代码行数尽可能维持在 500 行以下,多做组件的拆分,逻辑做好隔离
-
hooks 命名请使用 use<具体方法名/组件名/动词/动名词><基于某个 hook,可空>
例: useShopListReducer useListenUnmount
-
通用 hooks 方法请写在顶层 hooks 文件夹,非通用方法在当前组件目录建 hooks 文件夹
-
组件的 key 原则上不可使用 index,若无唯一标识,需使用 index.toString()
-
行内不做事件的处理,始终另外定义处理函数传入行内
// bad <A onClick={() => { xxx; }} />; // good const handleAClick = () => {}; <A onClick={handleAClick} />;
-
没有内容的标签应写成闭标签形式
// bad <div></div> // good <div />
-
能使用解构的尽量使用解构,避免从一个 object 中取多个 key 时使用多行代码。
// bad const name = props.name; const age = props.age; // good const { name, age } = props;
-
字符串的拼接统一使用模板字符串。
// bad const description = name + "的年龄为" + age; // good const description = `${name}的年龄为${age}`;
-
公共组件始终要继承@/interface 下面的 ICommonComponentBase,以便于其他人使用公共组件时可以快速修改一些简单样式
-
条件表达式始终使用大括号包裹
// bad if (true) setState(xxx); // good if (true) { setState(xxx); }
-
三元表达式不可嵌套多层,当大于等于两层时,另外定义函数进行逻辑处理
// bad return A.name === "张三" ? (A.age === 18 ? true : false) : false; // good const verifyIdentity = (val) => { if (A.name === "张三") { if (A.age === 18) { return true; } return false; } return false; }; return verifyIdentity(A);
-
块与其他声明内容之间应保持一行空格
// bad const a = "张三"; const printName = (val) => { console.log(val, "name"); }; printName(a); // good const a = "张三"; const printName = (val) => { console.log(val, "name"); }; printName(a);
-
数字、字符串统一声明为常量或者枚举
// bad const height=50 + 40 + 30 // good const HEADER_HEGHT=30 const BODY_HEIGHT=50 const FOOTER_HEIGHT=40 // bad switch(queryDimension){ case 'LOCATION':...;break; case 'DATE':...;break; case 'SOURCE':...;break; default:break; } // good export enum EQueryDimension { LOCATION = 'LOCATION', DATE = 'DATE', SOURCE = 'SOURCE', } switch(queryDimension){ case EQueryDimension.LOCATION:...;break; case EQueryDimension.DATE:...;break; case EQueryDimension.SOURCE:...;break; default:break; }
-
多个并列元素缺少公共父节点时统一使用 Fragment 作为父节点
<> <Children1 /> <Children2 /> <Children3 /> </>
-
所有组件的属性、方法需要添加相应注释
// bad export interface IButtonProps { children: string size?: 'normal' | 'large' onClick?: () => void } // good export interface IExpandButtonProps extends Omit<React.HTMLAttributes<HTMLDivElement>, 'onChange'> { /** 是否展开 */ expand?: boolean /** 状态变更处理函数 */ onChange?: (val: boolean) => void }
-
公共组件不允许做破坏性改动。如果改动涉及范围很小,需征得涉及人员同意,共同调整代码,否则一律做好向上兼容
-
对于注释的代码需要保留,增加TODO,格式为TODO 大名 保留原因 问题编号 - 请保持每个文件无警告、无错误
例:TODO nhsoft.lsd 该代码之后需要重新开启 Mars-2320
-
未尽到部分,会由 Eslint 检测
2. 命名规范
-
文件/文件夹命名规范
说明 示例 pages 文件夹下第一层使用大驼峰命名 pages->Admin 页面级组件使用小驼峰命名,功能级组件使用大驼峰命名;
每个组件都要建立单独的文件夹,文件夹名为组件名,
文件夹内文件应为 index.tsx + index.scss(非必须);页面级:pages->Admin->products->productList
功能级:pages->Admin->products->productList->components->ProductTable大组件拆分出的细分功能组件,
在当前页面组件文件夹下新建 components 文件夹做汇总productList->components->ProductTable 图片名使用小驼峰命名,引入组件中时,别名使用大驼峰命名。 shop.svg => import Shop from ‘@/assets/shop.svg’ -
变量命名规范
名称 规则 示例 变量 采用小写驼峰命名 lowerCamelCase;
代码中的命名均不能以下划线打头,也不能以下划线或美元符号结束;
方法名、参数名、成员变量、局部变量都统一使用 lowerCamelCase 风格,必须遵从驼峰形式const totalQuantity = 1 常量 常量命名全部大写,单词间用下划线隔开,力求语义表达完整清楚,不要嫌名字长 MAX_STOCK_COUNT 组件 所有组件使用大驼峰命名 const ProductTable = ()=>{}
组件属性名称 小驼峰 <ProductTable column={} />
-
ts 声明规范
名称 规则 示例 interface 采用 I 打头的命名形式 export interface ICustomModalProps{}
type 采用 T 打头的命名形式 `export type TSaleChannel=‘WECHAT’ 字面量 字面量命名全部大写,单词间用下划线隔开,
力求语义表达完整清楚,不要嫌名字长`export type TDiscountType =“FULL_MONEY_REDUCE_MONEY” enum 采用 E 打头的命名形式,枚举的英文 key 与常量使用同样的命名规则 export enum ESaleChannel{ WECHAT='微信小程序',POS='POS'}
-
函数命名规范 如果是对外暴露的钩子,应以 on 开头;如果是组件内部的处理函数,则必须是 动词 或者 动词+名词;
行为 名称 新增 作为钩子:onAdd/onAddXXX,作为事件处理函数:handleAddXXX 保存 作为钩子:onSave/onSaveXXX,作为事件处理函数:handleSaveXXX 删除 作为钩子:onDelete/onDeleteXXX,作为事件处理函数:handleDeleteXXX 确认 作为钩子:onConfirm/onConfirmXXX,作为事件处理函数:handleConfirmXXX 取消 作为钩子:onCancel/onCancelXXX,作为事件处理函数:handleCancelXXX 改变 作为钩子:onChange/onXXXChange,作为事件处理函数:handleXXXChange 批量操作 作为钩子:onBatchXXX,作为事件处理函数:handleBatchXXX -
组件属性命名规范
属性 统一名称 显隐 visible 表单项标题 label 表单项值 value 表单默认值 defaultValue 标题 title -
集合命名规范
属性 统一名称 数组 XXXArr map XXXMap -
其他:
- 缩略名应全为大写
// bad const getHttpMethods = () => {}; // good const getHTTPMethods = () => {};
- css 类名:统一小写并使用“-”符隔开
例:.product-body-container{}
- 使用 global 修改组件库样式时,一定要在外层套一层 class,以限制作用域
.wrapper { width: 8rem; height: 8rem; cursor: pointer; :global(img) { max-width: 100%; max-height: 100%; } }
- 样式属性值为 0 时统一不带单位
.container { width: 0; }
3. 代码提交规范
- feat: 新功能
- fix: 修补某功能的 bug
- docs: 仅文档新增/改动
- style: 代码格式(不影响代码运行的格式变动,注意不是指 CSS 的修改)
- refactor: 重构某个功能
- test: 提交测试代码(单元测试,集成测试等)
- chore: 构建或辅助工具的变动
- misc: 一些未归类或不知道将它归类到什么方面的提交
- 还有一种特殊情况,如果当前 commit 用于撤销以前的 commit,则必须以 revert:开头,后面跟着被撤销 Commit 的 Header。 (): // 空一行// 空一行
- 【强制】尽量做到一个jira问题一次提交,不多提交也不少提交,每个提交对应一个codestream feedbackRequest。
- 【强制】应尽量将设计精细化拆分;做到小幅度修改,多次数提交,但应保证提交的完整性。
- 【强制】如果 message 可以关联 jira 问题编号,必须关联,方便找到修改哪个相应问题
- 【强制】提交人名需是本人全名
- 【强制】每个人单独一个分支,命名为“develop-名字首字母小写”,在有新的改动前, 先 rebase origin develop,如果本地 develop 是最新的, 也可以 rebase 本地的 develop, 如果当日有必要的 commit 最好在当日提交到 origin develop,merge 需要使用–no-ff 参数。
4. sdk、组件库临时更新规范
-
sdk 项目本地仓库 reset 到正式环境发布时的 sdk/组件库版本代码,例:git reset --hard xxx
-
进行临时更新的代码修改
-
本地 commit 代码
-
本地打临时更新 tag,例: git tag origin-
0.0
.187
-fix-2021112310
-m
’临时更新:xxxxxx’ -
拉取远端代码,合并冲突
-
本地打开发环境 tag,顺应版本号顺序递增一位,例:git tag
0.0
.188
-m
’更新内容描述’ -
推送代码
-
推送 tag
-
web/pos/小程序端项目新建临时更新分支
-
变更
package
.json 的依赖版本为临时更新版本号完成临时更新回到开发分支后,变更
package
.json 中依赖版本号为刚才推送的第二个 tag 的版本号,后续正常进行日常开发
5. 前端项目版本号管理策略
项目初次上线,初始版本统一规定为 1.0.0,版本号在如下情况下以对应的规则进行迭代(临时更新视为正常发版更新,同样遵循下面的规则):
- 当修改 Bug 和优化功能时,修改叠加第三位数字,其他不变,如 1.0.1
- 增加新功能时修改第二位数字,第三位数字清 0,如 1.1.0
- 有特别大的改动,需求功能大改时,第一位数字+1,后两位数字清 0,如 2.0.0
- 所有组件使用大驼峰命名
- 路由页面使用小驼峰命名
- pages文件夹下第一层使用大驼峰命名
- hooks命名请使用use<具体方法名或者组件名,如ShopList><基于某个hook,可空>,例如useShopListReducer
- 属性名称: React DOM 使用小驼峰命令来定义属性的名称,而不使用 HTML 属性名称的命名约定;
- 变量 :采用小写驼峰命名 lowerCamelCase,代码中的命名均不能以下划线,也不能以下划线或美元符号结束;方法名、参数名、成员变量、局部变量都统一使用 lowerCamelCase 风格,必须遵从驼峰形式
- 常量:常量命名全部大写,单词间用下划线隔开,力求语义表达完整清楚,不要嫌名字长。例如:MAX_STOCK_COUNT
- 函数:必须是 动词 或者 动词+名词 形式*,例如:saveShopCarData /openShopCarInfoDialog