封装组件的思路
封装组件时,需要先抽象组件的功能,比如一个form组件,里面包含input、select等子组件,那我们先从逻辑上拆分
1、我们最终业务使用的是一个整体form,里面包含input、select子组件,那这些子组件的共性和他们的差异点在哪里?
共性:
方法(如获取值、赋值等)
props(接收特定参数去控制组件部分逻辑及展示)
差异点:
样式
特性及逻辑
封装的目的其实就是抽出共性,将差异点放出去通过配置处理,这里贴一下大神写的react高阶组件
import React from 'react';
import AsyncValidator from 'async-validator';
class InputComponent extends React.Component {
render() {
const {form} = this.props;
return (
<div>
<input
{...form.getFieldProps(
'inputKey',
{
validator: [
{
min: 2,
max: 20,
message: '用户名长度为 2-20'
}
]
}
)}
/>
<div {...form.getFieldError('inputKey')} />
</div>
);
}
}
function FormCreate(options) {
const store = {};
return function(WrappedComponent) {
return class HOCWrappedComponent extends React.Component {
constructor(props) {
super(props);
this.getFieldProps = this.getFieldProps.bind(this);
}
getFieldProps(fieldKey, options) {
const self = this;
const validator = new AsyncValidator({[fieldKey]: options.validator});
return {
value: store[fieldKey] && store[fieldKey].value,
onInput(e) {
const value = e.target.value;
store[fieldKey] = {...store[fieldKey], value};
validator.validate({[fieldKey]: value})
.then(() => {
store[fieldKey].error = null;
self.forceUpdate();
})
.catch(({errors}) => {
store[fieldKey].error = errors.map(error => error.message);
self.forceUpdate();
})
}
};
}
getFieldData(fieldKey) {
return store[fieldKey] && store[fieldKey].value;
}
getFieldError = (fieldKey) => {
return {
children: store[fieldKey] && store[fieldKey].error
}
}
render() {
const form = {
getFieldProps: this.getFieldProps,
getFieldError: this.getFieldError
}
return (
<WrappedComponent form={form}></WrappedComponent>
);
}
}
}
}
const FormCreateComponent = FormCreate({data: 'hello world'})(InputComponent);
export default class extends React.Component {
render() {
return (
<FormCreateComponent />
);
}
}
这里做的就是相当于把子组件如input相关的特性放在组件里面自己实现,然后往上面一层抽离出共性,这里姑且先叫它组件生成器,然后最上层就是抛出去一个form组件供外部调用。
image.png
结合上图可以大概总结一些,我们最终得到的结果是一个整体,但是这个整体其实是由一个生成器生成不同类型的子组件,在生成器中我们支持参数定制一些配置或者属性,然后下面包含n种不同类型的子组件。
2、过程中可能会使用一些工具帮助处理
async-validator 一种表单校验工具
story-book 组件文档管理工具
lerna 包管理工具
babel-plugin-import 打包处理工具,可帮助实现组件的按需引入
react项目中暴露webpack配置可使用eject
3、封装组件的一些思考
我们为什么封装组件,怎样的组件才算是比较好的?
这里需要考虑几点,主题定制化、国际化、可访问性、单元测试这些都需要封装的时候考虑进需求,封装组件是为了更方便的去开发,所以最终目的只要能帮助写业务是提高效率,组件就是合格的。黑猫白猫能抓住老鼠的才是好猫。
在Vue中怎么实现高阶函数?
这里有两种方法,一种通过函数式组件去封装,还一种使用mixins去实现,一般在Vue项目中习惯性使用mixins会更多,和上面抽象的逻辑一样,mixins抽取共性,封装,然后差异性的点还是放在子组件去做,将一些配置化的东西抽离就可以。
网友评论