Appearance
命名规范
项目已集成eslint检查语法和规则错误。同时code spell checker查询拼写错误。
VSCode已集成插件,所以在VSCode中会标出错误的地方。提交MR之前请修复标出的错误。
MR提交的标准:
- 没有eslint报错
- 没有code spell checker报错
URL命名
前后端的URL分用户端和管理端,
后端管理端的API是/admin开头,用户端没有/admin:
- 后端用户端:
/api/v5/location-groups - 后端管理端:
/api/v5/admin/location-groups
前端管理端的页面是/admin开头,用户端/user:
- 前端用户端:
/user/location-groups - 前端管理端:
/admin/location-groups
- 后端用户端:
URL的path采用
name-name(snake)方式命名,多个单词用hyphen(-)隔开:ts@Get('/all-users') async findAllUsers() { ... }路径的命名和目录结构保持一致:
目录结构: - admin - users - AllUsers.tsx对应的URL:
/api/v5/admin/users/all-users
目录结构
- [前端目录结构](../../frontend/docs/project-structure.md)
- [后端目录结构](../../server/docs/architecture.md)
页面命名方式
列表页面 [模块名]List.tsx
详情页面 [模块名]Info.tsx
表单页面 [模块名]FormModal.tsx
模块名规范:<https://ao5vs9kqus.feishu.cn/wiki/MiNlwameziCYyKkdBiPctwHLnQg>
目录结构
```
- deliveries
- components
- DeliveryNameModal.tsx
- DeliveryTag.tsx
- deliveryCategories // 附属模块
- components
- DeliveryCategoryName.tsx
- DeliveryCategoryList.tsx
- DeliveryCategoryInfo.tsx
- DeliveryCategoryFormModal.tsx
- DeliveryList.tsx
- DeliveryInfo.tsx
- DeliveryFormModal.tsx
- DeliveryPage.tsx // 入口
```
组件命名
- 组件名称和文件名称一致
- 一个文件只export一个组件
- 所有的Modal都用NiceModal.create:
- 参数采用props; 如
props: EditUserModalProps需要定义interface: interface EditUserModalProps { record?: UserBookEntity }
函数命名
- camelCase
参数命名
- camelCase
事件处理函数
- onXXX
文件命名
- 文件名采用
camelCase命名:如locationGroup.ts - 唯一例外是React组件,采用
PascalCase: 如KBSelectUser.tsx index.ts,index.tsx用于export,不要定义class或component。
Class命名
- Typescript Class采用
PascalCase命名,如
ts
class LocationGroup {
...
}- Class名称除大小写外与文件名一致
国际化命名
- 命名采用'<模块>.<子模块>.<名称>'的方式: 如 'resource.statistics.title'。一般有子模块。也可以没有。采用英文'.'分隔。
- 名称采用camelCase.
- 模块名称和规定的常用名词一致。
- 跨模块的通常的操作或名词,如'add','edit','delete','No data',直接国际化,不用加模块名称。其他情况需要加模块名称。
- 国际化带参数: "预计今天{time}到达",需要传入参数。"新增{类型}",可共享同一个国际化字段 (
trAdd) - 复数形式
参数命名
- 参数采用
camelCase:
js
/* Bad */
const page_count = 5
const active = true
const ShouldUpdate = true
/* Good */
const pageCount = 5
const isActive = true
const shouldUpdate = true- 除Id外,不要采用缩写.
DO:
ts
const currentUser = ...
setCurrentUser(user1)DON'T
ts
const curUser = ...
setCurUser(user`)命名方式
Naming things is hard. Please adhere to the conventions here.
使用英文
Use English language when naming your variables and functions.
js
/* Bad */
const primerNombre = 'Gustavo'
const amigos = ['Kate', 'John']
/* Good */
const firstName = 'Gustavo'
const friends = ['Kate', 'John']简单直接的命名
A name must be short, intuitive and descriptive:
- Short. A name must not take long to type and, therefore, remember;
- Intuitive. A name must read naturally, as close to the common speech as possible;
- Descriptive. A name must reflect what it does/possesses in the most efficient way.
js
/* Bad */
const a = 5 // "a" could mean anything
const isPaginatable = a > 10 // "Paginatable" sounds extremely unnatural
const shouldPaginatize = a > 10 // Made up verbs are so much fun!
/* Good */
const postCount = 5
const hasPagination = postCount > 10
const shouldPaginate = postCount > 10 // alternatively避免重复
A name should not duplicate the context in which it is defined. Always remove the context from a name if that doesn't decrease its readability.
js
class UserService {
/* BAD: Method name duplicates the context (which is "User") */
getUserSettings(event) {
// ...
}
/* GOOD: Reads nicely as `userService.getSettings()` */
getSettings(event) {
// ...
}
}结果导向
A name should reflect the expected result.
jsx
/* Bad */
const isEnabled = itemCount > 3
if (!isEnabled) {
// ...
}
/* Good */
const isDisabled = itemCount <= 3
if (isDisabled) {
// ...
}命名方法
命名函数的原则:动词 + 模块 + 子模块
命名函数的原则:
前缀? + 动词 (A) + 模块 (HC) + 子模块? (LC)Take a look at how this pattern may be applied in the table below.
| 名字 | 前缀 | 动词(A) | 模块 (HC) | 子模块 (LC) |
|---|---|---|---|---|
getUser | get | User | ||
getUserMessages | get | User | Messages | |
shouldDisplayMessage | should | Display | Message | |
isPaymentEnabled | is | Enabled | Payment |
动词
The verb part of your function name. The most important part responsible for describing what the function does.
get
Accesses data immediately (i.e. shorthand getter of internal data).
js
function getUserFullName() {
return this.firstName + ' ' + this.lastName
}See also compose.
set
Sets a variable in a declarative way, with value A to value B.
js
let fruits = 0
function setFruits(nextFruits) {
fruits = nextFruits
}
setFruits(5)
console.log(fruits) // 5reset
Sets a variable back to its initial value or state.
js
const initialFruits = 5
let fruits = initialFruits
setFruits(10)
console.log(fruits) // 10
function resetFruits() {
fruits = initialFruits
}
resetFruits()
console.log(fruits) // 5fetch
Request for some data, which takes some indeterminate time (i.e. database request).
js
function getUsers() {
return this.userRepository
.createQueryBuilder()
.where('user.isActive = :isActive', { isActive: true })
.getMany()
}remove
Removes something from somewhere.
For example, if you have a collection of selected filters on a search page, removing one of them from the collection is removeFilter, not deleteFilter (and this is how you would naturally say it in English as well):
js
function removeFilter(filters, filterName) {
return filters.filter((name) => name !== filterName)
}
const selectedFilters = ['price', 'availability', 'size']
removeFilter(selectedFilters, 'price')See also delete.
delete
Completely erases something from the realms of existence.
Imagine you are a content editor, and there is that notorious post you wish to get rid of. Once you clicked a shiny "Delete post" button, the CMS performed a deletePost action, not removePost.
js
function deleteUser(id) {
return this.userRepository.delete(id)
}See also remove.
compose
Creates new data from the existing one. Mostly applicable to strings, objects, or functions.
js
function composePageUrl(pageName, pageId) {
return pageName.toLowerCase() + '-' + pageId
}See also get.
模块
A domain that a function operates on.
A function is often an action on something. It is important to state what its operable domain is, or at least an expected data type.
js
/* A pure function operating with primitives */
function filter(list, predicate) {
return list.filter(predicate)
}
/* Function operating exactly on posts */
function getRecentPosts(posts) {
return filter(posts, (post) => post.date === Date.now())
}Some language-specific assumptions may allow omitting the context. For example, in JavaScript, it's common that
filteroperates on Array. Adding explicitfilterArraywould be unnecessary.
--
前缀
Prefix enhances the meaning of a variable. It is rarely used in function names.
is
Describes a characteristic or state of the current context (usually boolean).
js
const color = 'blue'
const isBlue = color === 'blue' // characteristic
const isPresent = true // state
if (isBlue && isPresent) {
console.log('Blue is present!')
}has
Describes whether the current context possesses a certain value or state (usually boolean).
js
/* Bad */
const isProductsExist = productsCount > 0
const areProductsPresent = productsCount > 0
/* Good */
const hasProducts = productsCount > 0should
Reflects a positive conditional statement (usually boolean) coupled with a certain action.
js
function shouldUpdateUrl(url, expectedUrl) {
return url !== expectedUrl
}min/max
Represents a minimum or maximum value. Used when describing boundaries or limits.
js
/**
* Renders a random amount of posts within
* the given min/max boundaries.
*/
function renderPosts(posts, minPosts, maxPosts) {
return posts.slice(0, randomBetween(minPosts, maxPosts))
}单复数
js
/* Bad */
const friends = 'Bob'
const friend = ['Bob', 'Tony', 'Tanya']
/* Good */
const friend = 'Bob'
const friends = ['Bob', 'Tony', 'Tanya']