分支规则
主分支: master
开发分支: develop
功能开发以 `feature/功能名` 命名
组件开发以 `components/组件名` 命名
修复 bug 以 `bugfix/bug(bugId或简短名)` 命名
紧急修复以 `hotfix/bug` 命名
文档开发以 `docs/功能名` 命名
命名规则
统一命名规则
动态组件 统一使用 `tag` 属性来指定生成的标签类型
状态对应属性应该为直接的状态名
如: `loading` 状态对应属性名应该为 `loading`、`disabled` 状态对应属性名应该为 `disabled`
分子以上组件,内部出现多个组件有相同状态则以 [组件名][状态名] 小驼峰形式对外暴露
内部组件对外暴露 `class` 属性以 `[组件名][Class]` 小驼峰形式命名
`script`、`js` 中驼峰命名,文档、文件夹、模板中以 - 连接
数组类型以复数形式命名
例如: `options` 对应为 `array` 类型, `option` 对应为 `object` 类型
内部组件命名也应该符合命名规范
内部组件属性透传命名建议以 `[组件名]Props` 名称命名
例如: 导航组件使用 `logoProps` 属性对 `logo` 标签进行属性传递
内部响应事件函数应该以 `handle[EventName]` 命名, `update` 事件以 `update[PropName]` 命名,如果内部有多个相同的事件名,则以 `handle[Element/ComponentName][EventnName]` 命名
子组件有更改属性需求时,对外发送 `update:PropName` 事件,并且将新值当做第一个参数
代码块Vue.js Component<template>复制代码<div></div>复制代码</template>复制代码<script>复制代码export default {复制代码props: {复制代码visible: Boolean,复制代码},复制代码methods: {复制代码toggle () {复制代码this.$emit('update:visible', !this.visible);复制代码}复制代码}复制代码}复制代码</script>复制代码slot 命名应该明确表明该 slot 对应元素的意义
例如: <slot name='loading' /> 表明此插槽用来显示自定义的 loading 元素
// only an demo 复制代码
<script>复制代码
export default {复制代码
name: 'MtdButton',复制代码
props: {复制代码
// logo 地址复制代码
logo: String, 复制代码
// [组件/模块名]Props复制代码
logoProps: Object, 复制代码
// [组件/模块名]Class复制代码
logoClass: String, 复制代码
// 数组类型命名复数复制代码
options: Array, 复制代码
option: Object, 复制代码
},复制代码
methods: {复制代码
// handle[ComponentName][EventName]复制代码
handleInputClick () {复制代码
}复制代码
}复制代码
}复制代码
</script>复制代码
Props
样式相关枚举类型属性不做强校验、功能相关强校验
用户可能自己定义了其他样式并将改属性传入,所以对样式方面的枚举类型不做强校验,但是功能方面需要内部的支持,传入一个不支持的对于用户来说没有任何意义。
代码块Vue.js Component// tooltip component 复制代码<script>复制代码export default {复制代码name: 'MtdTooltip',复制代码props: {复制代码// 此属性用于生成对应的 class,内部样式只支持 dark、 light,但是不能排除用户提供了其他样式的可能,所以此处不校验复制代码theme: String, 复制代码// 此属性用于 tooltip 的显示触发方式,由于内部只实现了 hover,click 所以对于用户来说传递一个其他方式并没有意义复制代码trigger: { 复制代码type: String,复制代码validator: function (v) { 复制代码return ['hover', 'click'].includes(v);复制代码}复制代码}复制代码// ...other复制代码}复制代码// ...复制代码}复制代码</script>复制代码表单需要支持 `v-model`, 使用 .sync 修饰符表达更新 props 意图
代码块Vue.js Component// switch component 复制代码<script>复制代码export default {复制代码name: 'MtdSwitch',复制代码model: {复制代码prop: 'actived',复制代码},复制代码props: {复制代码actived: Boolean,复制代码},复制代码methods: {复制代码handleClick () {复制代码this.$emit('input', this.actived);复制代码}复制代码}复制代码}复制代码</script>复制代码上层组件需要支持内部组件属性透传,特别是要提供内部组件 `class` 传递
有些时候需要对内部进行样式的覆盖,如果不提供 `class` 支持,外部只能通过选择器的优先级完成.
代码块Vue.js Component// 分页组件分为 Pagination, Pager复制代码// Pagination component 复制代码<template>复制代码<ss-pager v-bind="$attrs" :class="pagerClass"></ss-pager>复制代码// or复制代码<ss-pager v-bind="pagerProps"></ss-pager>复制代码// ...复制代码</template>复制代码<script>复制代码export default {复制代码name: 'MtdPagination',复制代码props: {复制代码pagerClass: string,复制代码}复制代码}复制代码</script>复制代码复制代码组件作用对应某一个原生标签时,需要使用 `v-bind="$attrs"` ,对应的也可以使用 `v-on="$lisenters"`
这样做可以不用显示的定义全原生标签属性,而且当原生属性扩展时不需要更变
代码块Vue.js Component// input component复制代码<template>复制代码// ...复制代码<input v-bind="$attrs" />复制代码</template>复制代码组件避免出现不同属性控制相同功能、样式
代码块Vue.js Component// pager component复制代码// 不推荐复制代码<script>复制代码export default {复制代码props: {复制代码total: Number,复制代码pageCount: Number,复制代码pageSize: Number,复制代码}复制代码}复制代码</script>复制代码复制代码// 推荐复制代码<script>复制代码export default {复制代码props: {复制代码total: Number,复制代码pageSize: Number,复制代码}复制代码computed: {复制代码pageCount () {复制代码return Math.ceil(total/pageSize) || 0;复制代码}复制代码}复制代码}复制代码</script>复制代码
Data / State
组件无状态,控制权交与使用者
代码块Vue.js Component// switch component复制代码<script>复制代码export default {复制代码props: {复制代码actived: Boolean,复制代码},复制代码methods: {复制代码handleClick () {复制代码this.$emit('input', !this.actived); // 此时如果外部没有改变 actived 属性的值,显示依然会是原来的状态复制代码}复制代码}复制代码}复制代码</script>复制代码优先使用计算方式得出当前所需内部属性 (vue 中的 computed)
例如: tabs 组件中,tab 组件会有 active 的状态,active 的状态应该由计算属性得出来,而不是通过 watch 来改变内部变量
代码块JavaScript// better 复制代码get active () { 复制代码return tabsValue === this.value 复制代码} 复制代码// not 复制代码watch { 复制代码tabsValue (n) { 复制代码this.active = n === this.value 复制代码} 复制代码} 复制代码避免出现内部属性的使用 (vue 的 data 函数, react 的 state)
Event
在父子组件通信、属性方法定义时,当不需要方法的返回值时,原则上都应该使用事件的方式 ( Vue )
代码块JavaScript// 不推荐复制代码export default {复制代码name: 'MtdInput',复制代码props: {复制代码onChange: Function,复制代码},复制代码methods: {复制代码handleInput (v) {复制代码this.onChange(v);复制代码}复制代码}复制代码}复制代码复制代码// 推荐复制代码export default {复制代码name: 'MtdInput',复制代码methods: {复制代码handleInput (v) {复制代码this.$emit('input', v);复制代码}复制代码}复制代码}复制代码组件应该支持常用的原生事件,原生事件第一个参数应该是 event 对象
代码块Vue.js Component<template>复制代码<div>复制代码<input v-bind="$attrs" v-on="$lisenters" :value="value" @input="handleInput" /> 复制代码</div>复制代码</template>复制代码<script>复制代码export default {复制代码name: 'MtdInput',复制代码props: {复制代码value: [String, Number]复制代码},复制代码// ...other复制代码}复制代码</script>复制代码原生类型事件,其行为应该同原生事件 例如: compositionstart、compositionend 事件,应该表现同原生,不应该对外发送 change 类型事件
change、update 类型事件第一个参数是 新值,第二个参数是 旧值
代码块Vue.js Component<template>复制代码<div></div>复制代码</template>复制代码<script>复制代码export default {复制代码props: {复制代码visible: Boolean,复制代码},复制代码methods: {复制代码handleClose () {复制代码this.$emit('update:visible', false, this.visible);复制代码}复制代码}复制代码}复制代码</script>复制代码事件、方法参数应该避免超过3个,且越常用的参数应该越靠前
方法中最后一个参数不应该是 bool 类型,应该将所有 bool 类型参数改为 object
代码块JavaScript// 不推荐: 复制代码function doSomthing (param, replace /* bool */) 复制代码// 推荐: 复制代码function doSomthing (param, { replace /* bool */ }) 复制代码
组件通信
统一使用 事件 方式向父级通信,父级通过更改 prop 做出回应
避免使用 refs
避免使用 $parent
Vue.js 支持组件嵌套,并且子组件可访问父组件的上下文。访问组件之外的上下文违反了基于模块开发的第一原则。因此你应该尽量避免使用 this.$parent
其他
组件内部不要出现魔数,如果确实有需求需要使用,必须添加注释,描述清楚数值的作用及来源,如果可能更改(该值可能出现自定义的需求),则将其作为属性,默认值为当前值
样式相关需求优先考虑 `css` 或 `scss` 变量方式,如果 `css`、`scss` 实现不了,则需要在 `js` 实现时添加注释说明原因
将样式与 `js` 分离,方便用户做样式覆盖,如果写在了 `js` 中则很大概率会使用 `style` 方式来生成样式,对于用于自定义样式来说非常困难,而且,各个页面、组件之间样式很可能有一定的关联性,一部分在 `css` 中,一部分在 `js` 中不利于管理
1187

被折叠的 条评论
为什么被折叠?



