@[toc]
高階組件
什么是高階組件
高階組件就是一個(gè) React 組件包裹著另外一個(gè) React 組件
其中“包裹”的概念刹淌,因?yàn)樗赡軙?huì)有以下兩種不同的含義之一:
- Props Proxy: HOC 對傳給
WrappedComponent
的porps
進(jìn)行操作, - Inheritance Inversion: HOC 繼承
WrappedComponent
察滑。
Props Proxy
//Props Proxy 最簡實(shí)現(xiàn)
function ppHOC(WrappedComponent) {
return class PP extends React.Component {
render() {
return <WrappedComponent {...this.props} />
}
}
}
使用 Props Proxy 可以做什么
? 操作 props
? 通過 Refs 訪問到組件實(shí)例
? 提取 state
? 用其他元素包裹WrappedComponent
1.操作 props
function ppHOC(WrappedComponent) {
return class PP extends React.Component {
render() {
const newProps = {
id: newId
}
return <WrappedComponent {...this.props} {...newProps} />
}
}
}
2.通過 Refs 訪問到組件實(shí)例
function refsHOC(WrappedComponent) {
return class RefsHOC extends React.Component {
proc(wrappedComponentInstance) {
wrappedComponentInstance.method()
}
render() {
const props = Object.assign({}, this.props, { ref: this.proc.bind(this) })
return <WrappedComponent {...props} />
}
}
}
const refHoc = WrappedComponent => class extends Component {
componentDidMount() {
console.log(this.instanceComponent, 'instanceComponent');
}
render() {
return (<WrappedComponent
{...this.props}
ref={instanceComponent => this.instanceComponent = instanceComponent}
/>);
}
};
3.提取 state
function ppHOC(WrappedComponent) {
return class PP extends React.Component {
constructor(props) {
super(props)
this.state = {
name: ''
}
this.onNameChange = this.onNameChange.bind(this)
}
onNameChange(event) {
this.setState({
name: event.target.value
})
}
render() {
const newProps = {
name: {
value: this.state.name,
onChange: this.onNameChange
}
}
return <WrappedComponent {...this.props} {...newProps} />
}
}
}
@ppHOC
class Example extends React.Component {
render() {
return <input name="name" {...this.props.name} />
}
}
4.包裹WrappedComponent
function ppHOC(WrappedComponent) {
return class PP extends React.Component {
render() {
return (
<div style={{ display: 'block' }}>
<WrappedComponent {...this.props} />
</div>
)
}
}
}
Inheritance Inversion
Inheritance Inversion 最簡實(shí)現(xiàn)
function iiHOC(WrappedComponent) {
return class Enhancer extends WrappedComponent {
render() {
return super.render()
}
}
}
調(diào)用順序
didmount→HOC didmount→will unmount→HOC will unmount
使用 Inheritance Inversion可以做什么
? 渲染劫持
? 操作 state
1.渲染挾持
? 有條件地渲染元素樹
const MyContainer = (WrappedComponent) => class extends WrappedComponent {
render() {
if (this.props.loggedIn) {
return super.render();
} else {
return null;
}
}
}
? 讀取和修改由 render 輸出的 React 元素樹
const MyContainer = (WrappedComponent) => class extends WrappedComponent {
render() {
const elementsTree = super.render();
let newProps = {};
if (elementsTree && elementsTree.type === 'input') {
newProps = { value: 'may the force be with you' };
}
const props = Object.assign({}, elementsTree.props, newProps);
const newElementsTree = React.cloneElement(elementsTree, props, elementsTree.props.children);
return newElementsTree;
}
}
2.操作state
高階組件可以讀取、修改 WrappedComponent 實(shí)例中的 state修肠,如果需要的話贺辰,也可以 增加 state。但這樣做嵌施,可能會(huì)讓 WrappedComponent 組件內(nèi)部狀態(tài)變得一團(tuán)糟饲化。
const MyContainer = (WrappedComponent) => class extends WrappedComponent {
render() {
return (
<p>
<p>Props</p>
<pre>{JSON.stringify(this.props)}</pre>
<p>State</p>
<pre>{JSON.stringify(this.state)}</pre>
{super.render()}
</p>);
}
}
裝飾器
高階組件可以看做是裝飾器模式(Decorator Pattern)在React的實(shí)現(xiàn)。即允許向一個(gè)現(xiàn)有的對象添加新的功能吗伤,同時(shí)又不改變其結(jié)構(gòu)吃靠,屬于包裝模式(Wrapper Pattern)的一種
ES6中添加了一個(gè)decorator的屬性,使用@符表示足淆,可以更精簡的書寫巢块。
function HOCFactoryFactory(...params) {
// do something with params
return function HOCFactory(WrappedComponent) {
return class HOC extends React.Component {
render() {
return <WrappedComponent {...this.props} />
}
}
}
}
HOCFactoryFactory(params)(WrappedComponent)
//或
@HOCFatoryFactory(params)
class WrappedComponent extends React.Component{}
該篇文章借鑒了沈老師的總結(jié)筆記,還有許多大佬的博客巧号,如果有涉及侵權(quán)的族奢,請聯(lián)系我刪除。