搭建服务端
yarn add express
yarn add nodemon
在server目录下 npm init -y
// 增加dev脚本
"scripts": {
"dev": "nodemon ./index.js"
},
引入
HOC
- High Order Component 高阶组件,是组件的抽象
- HOC不是React提供的API,高级的设计模式
- HOC是一个函数,接收一个组件参数,返回一个新组件
- 普通组件返回的是UI,HOC返回的是一个新组件
- HOC不能修改参数组件,只能传入组件所需要的props(否则可能会导致参数组价内部的逻辑执行失效)
- HOC是一个没有副作用的纯函数
- HOC除了必须填入被包裹的组件参数以外,其余参数根据需求增加
- HOC不关心数据如何使用,包裹组件不关心数据从哪来,只做渲染
- HOC和包裹组件直接唯一的契合点是props
代码
完整代码
git
- index15.jsx
import { fetchListData } from "./index15/front-end/model"
import { listHoc } from './index15/front-end/components/listHoc'
import StudentList from './index15/front-end/components/StudentList'
import TeacherList from './index15/front-end/components/TeacherList'
const StudentListHoc = listHoc(StudentList, fetchListData)
const TeacherListHoc = listHoc(TeacherList, fetchListData)
class App extends React.Component {
render() {
return (
<>
<StudentListHoc field='student' />
<TeacherListHoc field='teacher' />
</>
)
}
}
ReactDOM.render(
<App />,
document.getElementById('app')
)
- listHoc .jsx
export function listHoc(WrapperComponent, fetchListData) {
return class extends React.Component {
state = {
listData: []
}
remove = (id) => {
this.setState({
listData: this.state.listData.filter(item => item.id !== id)
})
}
like = (id) => {
this.setState({
listData: this.state.listData.map(item => {
if (item.id == id) {
item.like = Number(item.like) + 1
}
return item
})
})
}
async componentDidMount() {
const res = await fetchListData(this.props.field)
this.setState({
listData: res.data
})
}
render() {
return (
<>
{
this.props.field === 'student' ?
<WrapperComponent
data={this.state.listData}
removeStudent={this.remove}
></WrapperComponent>
:
<WrapperComponent
data={this.state.listData}
likeTeacher={this.like}
></WrapperComponent>
}
</>
)
}
}
}
高阶组件横切关注点
- 横切关注点 → minxins
- 对参数组件本身的逻辑状态与视图的横向切割
- 让HOC来完成逻辑和状态的管理
- 让参数组件来完成视图的渲染
- 让HOC将数据与逻辑传递到参数组件中,从而完成关注点分离且有机结合的任务
柯里化
- index.jsx
const StudentListHoc = listHoc(StudentList)(fetchListData)
const TeacherListHoc = listHoc(TeacherList)(fetchListData)
- listHoc .jsx
export function listHoc(WrapperComponent) {
return function (fetchListData) {
return class extends React.Component {
......
}
}
}
还可以在
StudentList子组件内部返回listHoc(StudentList)
注意事项
有value就必须有onChange,否则使用defaultValue
- 使用剩余参数去排除不需要的属性
- 对“HOC不能修改参数组件”的理解,例如,如下修改参数组件的生命周期函数
- MyInput.jsx
export default class MyInput extends React.Component {
componentDidUpdate() {
console.log('MyInput更新')
}
render() {
return (
<div>
<h1>{this.props.inputValue}</h1>
<p>总计:{this.props.b + this.props.c}</p>
<input
type="text"
placeholder="请填写"
value={this.props.inputValue}
onChange={this.props.valueInput}
/>
</div>
)
}
}
- InputHoc
export function InputHoc(WrapperComponent) {
// 注意 如果在这里修重写生命周期函数componentDidUpdate
// WrapperComponent内的componentDidUpdate将不会被触发
// WrapperComponent.prototype.componentDidUpdate = () => {
// console.log('InputHoc内重写componentDidUpdate')
// }
return class InputHocComponent extends React.Component {
componentDidUpdate() {
console.log('不重写,都触发')
}
state = {
inputValue: ''
}
valueInput = (e) => {
this.setState({
inputValue: e.target.value
})
}
render() {
// 排除参数组件中不需要的属性
// 注意 剩余参数时变量名必须叫props
const { a, ...props } = this.props
return (
<WrapperComponent
inputValue={this.state.inputValue}
valueInput={this.valueInput}
{...props}
/>
)
}
}
}
- index.jsx
import MyInput from './index16/front-end/components/MyInput'
import { InputHoc } from './index16/front-end/components/InputHoc'
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.getElementById('app')
)



- MyInput使用函数组件
export default function MyInput(props) {
return (
<div>
<h1>{props.inputValue}</h1>
<p>总计:{props.b + props.c}</p>
<input
type="text"
placeholder="请填写"
value={props.inputValue}
onChange={props.valueInput}
/>
</div>
)
}

2054

被折叠的 条评论
为什么被折叠?



