设计原则
一致性
- **与现实生活一致:**与现实生活的流程、逻辑保持一致,遵循用户习惯的语言和概念;
- **在界面中一致:**所有的元素和结构需保持一致,比如:设计样式、图标和文本、元素的位置等。
效率
- **简化流程:**设计简洁直观的操作流程;
- **清晰明确:**明确输入输出
易扩展
- 不掺杂明确的业务属性
- 提供合理的插槽自定义
辅助代码分离
一个有效的原则就是将辅助代码分离出来放在特定的地方,这样你在处理组件时就不必考虑这些。以下列举一些方面:
- 配置代码
- 假数据
- 大量非技术说明文档
组件模板中使用简短的表达式
- 复杂的行内表达式可读性比较差
- 行内表达式不能在其他地方复用,会导致代码冗余
- IDE不支持行内式表达式的语法校验
- 将复杂的语法移动到methods或者计算属性中
扁平的化props
- **组件的props根据实际情况进行合理拆解:**props只传递简单类型数据和函数,让组件的api看起来更像原生html的属性,并且让代码维护者和协作开发者明白传什么参数,不然的话如果props传递复杂数据类型,让你的组件很难重构,也会造成代码冗余。
假如我们现在一个对象数据源form,这个对象里面拥有的属性是一个零散的集合,里面有哪些属性自己并不尽知,并且组件只需要使用这个对象其中一部分的属性,这时我们应该对prop进行拆解。
/* bad */
<list-item :form="form"/>
/* good */
<list-item :phone="form.phone" :name="form.name" />
- **组件的props定义规范化:**属性设置默认值;属性设置数据类型校验;使用组件之前检查props是否存在。
/* good */
props: {
modelData: {
type: Array,
default: () => []
},
roleData: {
type: Object,
default: () => ({})
},
isSelect: {
type: Boolean,
default: false
},
selectTitle: {
type: String,
default: ''
}
}
更加纯粹的状态变化
对状态的更改通常应该响应某种事件,例如用户单击按钮或 API 的响应。此外它们不应该因为别的状态的变化而做出响应,因为状态之间这种关联可能会导致难以理解和维护的组件行为,状态变化应该没有副作用。
/* good */
watch: {
pagination() {
this.getDataFromApi()
},
searchText: {
handler() {
// 重置页码
if(this.pagination.page > 1) {
this.pagination.page = 1
return;
}
this.getDataFromApi()
}
}
},
当分页改变时,应用首先会通过 pagination 的处理函数重新获取数据。因此,如果我们改变了分页,我们并不需要去关注数据更新这段逻辑。
与实际业务代码松耦合
组件内代码只涉及到组件内部逻辑的实现,如果涉及到具体业务,因通过一些方式抽离出来,以此来增强组件的可复用性。大致的方式有以下两种:
- 涉及到布局和样式的代码通过插槽分离到父组件去,以此来实现组件可以再各种布局场景下进行更好的复用
// delete-modal组件里定义插槽
<isc-dialog :visible="dialogVisible" :before-close="handleClose">
<slot name="content"></slot>
</isc-dialog>
// 父组件中,可自定义组件内容
<delete-modal :dialogVisible.sync="dialogVisible" :title="'物模型'" @deleteClick="handleDelete">
<template v-slot:content>
<p>确认删除"{{ deleteData.name }}"物模型吗?</p>
</template>
</delete-modal>
- 涉及到接口调用,使用emit定义事件降低代码耦合性
//category-selec组件
<select @change="selectedChange"></select>
methods: {
selectedChange(value) {
this.$emit('change', value);
}
}
// 父组件触发传来的api请求事件
<category-select @change="getData" />
methods: {
getData(value) {
const res = await service.get('/api/data', {
id:value
});
}
}