风格约定
But not limited to代码风格
, there are other默认约定
.
Code organization and stratification
Code organization is a benevolent see benevolence and the wise see wisdom of the topic, there is no silver bullet . But no matter how change, guidelines or constant high cohesion and low coupling .
Strongly recommended two articles to broaden your horizons, take you to new heights.
Manage complexity with the front end of projects Feature First
Code organization Elegant, modular to be able to do a good job.
Stratified
According to the different functions of different dimensions hierarchy division after division level, further module division (in principle, each folder is a module)
Folder and file names
Choose their own style.
-
Folders and files using the kebab-case
kebab-case heavy user may select this.
-
Folders using Kebab-Case , document use Pascal Case
This is the recommended.
文件夹:event-bus 文件:EventBus.ts 复制代码
-
exception
- index files are not bound by the above
- Tool automatically generates a file (consider yourself bound)
The modular principle
Modular code first to do hierarchical code, isolation, abstract.
Different modules perform different functions, coordination between the different functions of each other.
-
Each module maintains an inlet and outlet
For external module, the inlet try to ensure a
For internal sub-module, the outlet try to ensure a
If you follow the folder as a module boundaries, each folder has a lower outlet (may default index file)
-
Entrance default index name of the module or folder name
// 例如: group文件夹 group/ |---index.ts // A. 默认作为入口 |---group.ts // B. 也可以默认作为入口 二者任选其一就好,A方案应该是大家默认的方案;B方案,检索代码的时候更方便 复制代码
-
Layered internal module
Internal module can also have
base
,common
,components
,helper
,utils
,filter
,config
and other levels (Ciqiong .....)
import
And export
principles
-
import
Import, assigned to the fileSpecify the file to be able to increase the speed of compiler package
// 指定到index文件 import { Logger } from './common/index'; 复制代码
common
Module
Independent article explains.
router
Module
router
Module style conventions.
Modular structure
router
├── helper
│ ├── ImportRoute.ts
│ └── RouteGenerator.ts
├── modules
│ ├── AboutRoutes.ts
│ └── HomeRoutes.ts
├── router.ts
└── Routes.ts
复制代码
-
helper: Help tool methods
-
modules: different business modules
-
router: vue-router initialization place, but also the module inlet
-
Routes:
RouteConfig
outlet, the other modules are available hereroute
arranged, so as to achieve the purpose of decoupling, in particular differentviews
inside of routing jumps, usingRoutes
the configuration to achieve the purpose of decoupling.example:
import { HomeRoute } from 'Routes'; // 跳转,这样没有硬编码任何的route信息,全部都是从Routes配置来,达到解耦的目的。 this.$router.push({ name: HomeRoute.name }) 复制代码
modules
Sub-module
File name:
views
folder name (module name) + the end of Routesthe modules file, folder views, and preferably one correspondence, and easy maintenance (a higher understanding segmentation module)
例如:
views
├── group
│ ├── xxx1.vue
│ └── xxx2.vue
├── report
│ ├── xxx3.vue
│ └── xxx4.vue
├── Home.vue
复制代码
modules
Correspondence is
例如:
router
├── modules
│ ├── GroupRoutes.ts
| ├── ReportRoutes.ts
│ └── HomeRoutes.ts
复制代码
Export Module Configuration:
// HomeRoutes.ts
export const HomeRoute = {
path: '/',
name: 'HomeRoute',
component: 'Home',
};
// 必须导出一个数组,因为是一个模块的配置信息,可能有多个配置,还可以进行配置层级关系
export default [HomeRoute];
复制代码
Note: This is just a thought, the specific operation but also flexibility.
RouteConfig
Style Conventions
-
RouteConfig
variable namevue
Route the end of the file name +// 文件Home.vue // 变量名HomeRoute export const HomeRoute = { path: '/', name: 'HomeRoute', component: 'Home', }; 复制代码
-
name
AttributesAnd
RouteConfig
variable names consistent -
component
AttributesIf asynchronous loading ,
component
need to use with respect toviews
thepath
format, because in theImportRoute
process of unification.// ImportRoute.ts统一处理 export function importRoute(file: string) { // @see https://github.com/webpack/webpack/issues/1949 return () => import(/* webpackChunkName: "chunk-[request][index]" */ '@/views/' + file + '.vue'); } 复制代码
-
path
AttributesThere is no best practice, it is best to use
restful
style constraintsIf
route.query
the parameter passed the like, breadcrumbs difficult to handle. -
meta
AttributesNot best practice, there are so few properties in most cases
export const HomeRoute = { path: '/', name: 'HomeRoute', component: 'Home', // component: () => import('@/views/Home.vue') meta: { // title的值可以为`i18n`的语言文件key,方便做国际化 title: '首页', // 作为menu.title和breadcrumb.title备选 icon: '', // icon的class,作为menu.icon和breadcrumb.icon备选 menu: { title: '首页', visible: true, icon: '', // icon的class }, breadcrumb: { title: '路径名', visible: false, // 有的时候不需要在面包屑上渲染 icon: '', // icon的class }, auth: { roles: [1, 2, 3] } } }; 复制代码
-
props
AttributesRouting component parameter passing , more advanced usage, see the examples
Use
props
mannercomponents
and$route
decoupled, socomponents
may be used alone or as a sub-assembly for use , and easy to test.Special scene may not be used
props
, for example, have never been common components, the components need to be used in combination Sons of, and can beroute
coupled.If
props
is settrue
,route.params
it will be set to the component properties.// 函数式(动态) const router = new VueRouter({ routes: [{ path: '/search', component: SearchUser, // route是SearchUser内部的this.$route props: (route) => ({ query: route.query.q }) }] }) 复制代码
// 静态 const router = new VueRouter({ routes: [{ path: '/promotion/from-newsletter', component: Promotion, props: { newsletterPopup: false } }] }) 复制代码
store
Module
vue
Application of module status
Modular structure
store
├── StoreTypes.ts # actions mutations getters类型
├── Actions.ts # 根级别的 action
├── Mutations.ts # 根级别的 Mutations
├── Getters.ts # 根级别的 getters
├── modules # 模块
│ ├── xxxStore.ts # 子模块
│ ├── SystemStore.ts # SystemStore子模块
├── index.ts # 入口
复制代码
-
index
: As entrance -
StoreTypes
As a type of constants fileReference constant use alternative -mutation- event type
Therefore, all types of mutation and the action of the constant use, easy to store other modules and the decoupling module.
modules sub-module
File name: Module name + ending Store
Business store in modules, corresponding to the best folder and files under views, easy maintenance
# 例子:
LocaleStore.ts # i18n模块
LoginStore.ts # 登录模块
UserStore.ts # 用户模块
复制代码
Store module
Promise
The main convention
module
internal code structure is as follows:
SystemStore
For example:
-
You need to use the prefix where using the module name as a prefix
Example the module name is
System
Generally agreed statement following sequence : In addition some of the other state are optional
- state declaration (for
systemState
example: ) - getter types statement (optional, flexible use)
- getters statement (optional, flexible use)
- mutation types statement (optional)
- mutations statement (optional)
- action types statement (optional)
- actions Statement (optional)
- store options Export
// 例子: SystemStore.ts
// 声明state
const systemState: SystemState = {
initialized: false,
};
// 声明GetterTypes
export const SystemGetterTypes = {
IS_SYSTEM_INITIALIZED: 'IS_SYSTEM_INITIALIZED',
};
// 声明getters
const getters = {
[SystemGetterTypes.IS_SYSTEM_INITIALIZED](state: SystemState, getters: any, rootState: any){
return state.initialized;
}
};
// 声明MutationTypes
export const SystemMutationTypes = {
SYSTEM_SET_INITIALIZED: 'SYSTEM_SET_INITIALIZED',
};
// 声明mutations
const mutations: MutationTree<SystemState> = {
[SystemMutationTypes.SYSTEM_SET_INITIALIZED]: (
state: SystemState,
payload: boolean
) => {
state.initialized = payload;
logger.log('system-store.initialized: ' + payload);
},
};
// 声明ActionTypes
export const SystemActionTypes = {
SYSTEM_UPDATE_INITIALIZED: 'SYSTEM_UPDATE_INITIALIZED',
SYSTEM_RESET: 'SYSTEM_RESET',
SYSTEM_INIT: 'SYSTEM_INIT',
};
// 声明actions
const actions = {
[SystemActionTypes.SYSTEM_UPDATE_INITIALIZED]: (
{ commit }: ActionContext<SystemState, any>,
initialized: boolean
) => {
commit(SystemMutationTypes.SYSTEM_SET_INITIALIZED, initialized);
},
[SystemActionTypes.SYSTEM_RESET]: ({
commit,
dispatch,
}: ActionContext<SystemState, any>) => {
// 清空所有使用store储存的数据.
},
[SystemActionTypes.SYSTEM_INIT]: (
{ commit, dispatch }: ActionContext<SystemState, any>,
payload: {
user: UserModel;
userCookie: UserCookie;
}
) => {
// 初始化数据
},
};
// 导出storeOptions
const storeOptions = {
state: systemState,
getters,
mutations,
actions,
};
export default storeOptions;
复制代码
Note : where the action types, mutation types and getter types are not mandatory, the es6
use of the official environment mapState
, mapGetters
, mapActions
, mapMutations
utility functions more convenient.
api
Module
api
Module is the interface service layer, mainly to do some conversion processing parameters, as well as other business decoupling layer.
Modular structure
Referring generally to modular structure
api
├── api.ts # 入口
└── modules # 子模块
├── DictionaryService.ts # 具体的业务模块
├── GroupService.ts
├── HistoryService.ts
复制代码
service module
Promise
File name: the end of the module name + Service
Business service under the modules, and the corresponding folder views, and easy maintenance
If too many service module interfaces corresponding to a single service files, folders can be further divided.
//例子:LoginService
// 声明url,导出url方便mock模块使用
export const GET_SIGN_IN = '/api/login';
// 声明service函数
export function signIn(data: {account: string; pass: string}) {
return ajax({
url: GET_SIGN_IN,
data,
method: 'post'
});
}
复制代码
URL prefix convention:
Query: Use
GET
as a prefix (except in special circumstances)Update: Use
UPDATE
New: Use
ADD
Delete: Use
DELETE
Other: EXPORT, IMPORT, UPLOAD, DOWNLOAD, etc.
service function name prefix convention:
- For a single entity may consider using get, add, update, delete prefixed
i18n
Module
The main recommendations are divided under the agreed code.
Modular structure
i18n
├── i18n.ts
├── index.d.ts
└── locales
├── en_US.js
├── modules
│ └── actions
│ ├── en_US.js
│ └── zh_CN.js
└── zh_CN.js
复制代码
Language file organization
Organization language modules, according to the main module (folder hierarchy) to organize, the minimum can reduce the likelihood of conflict.
Language file conventions:
- Dialect file in
locals
folder - File dialect coded name
Examples of hierarchical organization:
views
├── account
│ ├── Account.vue
│ ├── locales
│ │ ├── en_US.js
│ │ └── zh_CN.js
│ └── XXX.vue
├── feedback
│ ├── locales
│ │ ├── en_US.js
│ │ └── zh_CN.js
│ └── Suggestion.vue
├── locales
│ │ ├── en_US.js
│ │ └── zh_CN.js
复制代码
// views/feedback/locales/zh_CN.js
export const feedbackModule = {
// 语言模块属性:模块名+module结尾
// 可选的方式就是:严格按照文件夹层次来构造属性层级(缺点取属性值时太长,后期可以使用__dirname自动生成)
label: '您的意见:',
textarea: {
placeholder: '请写下您的意见与建议, 500字符以内'
}
};
复制代码
// views/locales/zh_CN.js
import feedbackModule from '../feedback/locales/zh_CN.js';
export default {
// 如果模块众多建议加上views
// views: {
// ...feedbackModule,
// }
// 如果模块少,直接
feedbackModule,
};
复制代码
// i18n/locales/zh_CN.js
import viewsLocales from '../../views/locales/zh_CN';
export default {
...viewsLocales
}
复制代码
mock
Module
mock data simulation module of work to do
Modular structure
Referring generally to the structure of the sub-modules
mock
├── mock.js # 入口
└── modules # 子模块
├── LoginMock.js # 具体的业务模块
复制代码
mock module
Promise
File Name: ending mock module name +
mock files in modules, and
api
the module corresponding to the document, and easy maintenance
Methods conventions:
-
mock
A method and a moduleservice
request method corresponding toFor example:
LoginService
ThesignIn
mock module corresponds also calledsignIn
-
mock module
You need to provide asetup
methodUniform external switch for call setup method, as a mock module
example:
// LoginMock.js
import Mock from 'mockjs';
import { genSuccessResult, genFailResult } from './mock-utils';
import { GET_SIGN_IN } from '../api/api';
import Cookies from 'js-cookie';
const signIn = (data) => {
Cookies.set('SESSIONID', 'mock SESSIONID');
return genSuccessResult({
msg: '登陆成功',
});
}
export default {
setup() {
Mock.mock(GET_SIGN_IN, 'post', signIn);
}
}
复制代码
// mock.js
import loginMocker from './modules/login';
export const start = function() {
loginMocker.setup();
};
复制代码
// main.js
import mocker from './mock/mock'
if (process.env.NODE_ENV === 'development') {
mocker.start();
}
复制代码
Other modules
Other modules such as
filters
,directives
,test
There is no summary, after supplement.
Focus on micro-channel public number, find more exciting content
Reproduced in: https: //juejin.im/post/5d00bc9551882544d33ba037