高階組件
High Order Component
-
HOC是一種高級的設(shè)計模式 -
HOC是一個函數(shù),接收一個組件參數(shù),返回一個新組件 - 普通組件返回的是
UI,HOC返回的是一個新組件 -
HOC不能修改參數(shù)組件,只能傳入組件所需的props -
HOC是一個沒有副作用的純函數(shù) -
HOC除了必須填入被包裹的組件參數(shù)外,其他參數(shù)根據(jù)需求增加 -
HOC不關(guān)心數(shù)據(jù)如何使用,包裹組件不關(guān)心數(shù)據(jù)從哪里來 -
HOC和包裹組件唯一直接的契合點就是props
HOC 更加關(guān)注邏輯和狀態(tài)的管理,參數(shù)組件的邏輯與狀態(tài)訂閱;
參數(shù)組件基本只需關(guān)注視圖的渲染;
function fetchListData(field) {
return new Promise((resolve, reject) => {
resolve({
data: [
{
name: "zs",
age: 12,
score: 44,
},
{
name: "ls",
age: 12,
score: 44,
},
{
name: "ww",
age: 12,
score: 44,
},
],
});
});
}
function listHoc(WrapperComponent, fetchListData) {
return class extends React.Component {
state = {
listData: [],
};
async componentDidMount() {
const result = await fetchListData(this.props.field);
this.setState({
listData: result.data,
});
}
removeStd(name) {
this.setState({
listData: this.state.listData.filter((item) => item.name !== name),
});
}
render() {
return (
<WrapperComponent
data={this.state.listData}
removeStd={this.removeStd.bind(this)}
/>
);
}
};
}
class StudentList extends React.Component {
render() {
return (
<table border="1">
<thead>
<tr>
<th>Name</th>
<th>Age</th>
<th>Score</th>
<th>操作</th>
</tr>
</thead>
<tbody>
{this.props.data.map((item, index) => (
<tr>
<td>{item.name}</td>
<td>{item.age}</td>
<td>{item.score}</td>
<td onClick={() => this.props.removeStd(item.name)}>刪除</td>
</tr>
))}
</tbody>
</table>
);
}
}
const StudentListHoc = listHoc(StudentList, fetchListData);
class App extends React.Component {
render() {
return <StudentListHoc field="student" />;
}
}
ReactDOM.render(<App />, document.querySelector("#app"));
function InputHoc(WrapperComp) {
// 會導致原組件聲明周期中對應的函數(shù)不會執(zhí)行,相當于重寫
// 不能這樣修改,可能會導致組件內(nèi)部的邏輯失效
// WrapperComp.prototype.componentDidUpdate = function () {
// console.log("Input Hoc1");
// };
class InputComponent extends React.Component {
state = {
value: "",
};
// 這里和上面的重寫不沖突
// 可以在這里重寫函數(shù),與原組件內(nèi)部邏輯不沖突,用作對原組件邏輯的擴展
componentDidUpdate() {
console.log("Input Hoc2");
}
chgInput(e) {
this.setState({
value: e.target.value,
});
}
render() {
const { a, ...props } = this.props;
return (
<WrapperComp
value={this.state.value}
chgInput={this.chgInput.bind(this)}
{...props}
/>
);
}
}
// 可以改變別名
InputComponent.displayName = "InputHoc";
return InputComponent;
}
class MyInput extends React.Component {
componentDidUpdate() {
console.log("MyInput");
}
render() {
return (
<div>
<p>總計:{this.props.b + this.props.c}</p>
<p>
<input
type="text"
defaultValue={this.props.value}
onChange={this.props.chgInput}
/>
</p>
<p>{this.props.value}</p>
</div>
);
}
}
const MyInputHoc = InputHoc(MyInput);
class App extends React.Component {
state = {
a: 1,
b: 2,
c: 3,
};
render() {
return <MyInputHoc {...this.state} />;
}
}
ReactDOM.render(<App />, document.querySelector("#app"));