定义:高阶组件是参数为组件,返回值为新组件的函数。
组件是将 props 转换为 UI,而高阶组件是将组件转换为另一个组件。像 Redux 的 connect 和 Relay 的 createFragmentContainer。
基本使用
// 接收Cmp 返回新组件
const foo = Cmp => props => {
return (
<div className="customCmp">
<p>自定义新增的组件</p>
<Cmp {...props} />
</div>
)
}
function Child(props){
return <div>Child {props.name}</div>
}
const Foo = foo(Child) // Child 原组件 Foo 新组件
// 其也可链式使用
const Foo2 = foo(foo(Child)) // 多层叠加
// 使用处 page
<Foo name="123" />
复制代码
结合装饰器模式使用
要想实现这种写法,需要安装插件和配置。
npm install -D @babel/plugin-proposal-decorators
,
具体可度一下
// 装饰器只能⽤在class上, 问题1: 装饰的顺序是啥?
// child 被foo 等装饰了
@foo2
@foo
@foo
class Child extends Components {
render(){
return <div>child</div>
}
}
// use 已被装饰
<Child />
复制代码
注意:
不要在 render ⽅法中使⽤ HOC。
这不仅仅是性能问题 – 重新挂载组件会导致该组件及其所有⼦组件的状态丢失。
why?
render() {
// 每次调⽤ render 函数都会创建⼀个新的 EnhancedComponent
// EnhancedComponent1 !== EnhancedComponent2
const EnhancedComponent = enhance(MyComponent);
// 这将导致⼦树每次渲染都会进⾏卸载,和重新挂载的操作!
return <EnhancedComponent />;
}
复制代码
antd 表单案例
react 没有像vue 那种双向绑定的东西,所以在弄表单input 最初可能使用这样的形式:
class FPage extends Component {
constructor(props) {
super(props)
this.state = {
name: '',
password: ''
}
}
render(
<div>
<h3>state 自维护形式</h3>
<Input placeholder="name" value={name} onChange={ e => {
this.setState({name: e.target.value})
}} />
<Input placeholder="password" value={password} onChange={ e => {
this.setState({password: e.target.value})
}} />
</div>
)
}
复制代码
使用antd里的Form.create() 进行装饰实现:
Form.create() 里常用的几个方法:
- getFieldDecorator:⽤于和表单进⾏双向绑定
- getFieldsValue:获取⼀组输⼊控件的值,如不传⼊参数,则获取全部组件的值
- getFieldValue:获取⼀个输⼊控件的值
- validateFields 校验相关
- xxx 其他
2.x antd 使用
@Form.create()
class FPage2 extends Component {
submit = () => {
console.log("submit", getFieldsValue(), getFieldValue("name"));
};
render(){
console.log("props", this.props.form);
const {getFieldDecorator} = this.props.form;
return (
<div>
<h3>FormPage2</h3>
<Form>
<Form.Item label="姓名">
{
getFieldDecorator("name", {rules:[nameRules]})
(<Input placeholder="please input ur name" />)
}
</Form.Item>
// xxxx
</Form>
</div>
);
}
}
复制代码
表达组件实现数据收集、校验、提交特性,可通过⾼阶组件扩展。
来看看这个Form.create、 getFieldDecorator 的大致实现
export default function kFormCreate(Cmp){
return class extends Component {
constructor(props){
super(props)
this.state = {}
this.options = {}
};
handleChange(e){
// input 的change 事件
let {name, value} = e.target;
this.setState({[name]: value});
};
getFieldDecorator(){
// 扩张了Input 标签
this.options[field] = option;
return InputCmp => React.cloneElement(InputCmp,
{ name: field, value: this.state[field] || "",
onChange: this.handleChange // 控件 change 事件处理
});
};
getFieldsValue(){
return {...this.state};
};
getFieldValue(name){
return this.state[name];
};
validateFields(){};
render(){
// 实现了方法的扩展
return
(
<div className="cp">
<Cmp {...props}
getFieldDecorator = {this.getFieldDecorator}
getFieldsValue = {this.getFieldsValue}
getFieldValue = {this.getFieldValue}
validateFields = {this.validateFields}
/>
</div>
)
}
}
}
复制代码
antd源码?
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END