function a(x) {
x();
}
function b() {
alert('hello');
}
a(b);
复制代码
function a() {
function b() {
alert('hello');
}
return b;
}
a()();
复制代码
// WrappedComponent 就是传入的包装组件
function withHoc(WrappedComponent) {
return class extends Component {
render () {
return (
<WrappedComponent />
)
}
}
}
复制代码
// 受控组件
class Login extends Component {
state = {
username: '',
password: ''
}
onUsernameChange = (e) => {
this.setState({username: e.target.value});
}
onPasswordChange = (e) => {
this.setState({password: e.target.value});
}
login = (e) => {
// 禁止默认事件
e.preventDefault();
// 收集表单数据
const { username, password } = this.state;
alert(`用户名: ${username}, 密码: ${password}`);
}
render () {
const { username, password } = this.state;
return (
<div>
<h2>登录</h2>
<form onSubmit={this.login}>
用户名: <input type="text" name="username" value={username} onChange={this.onUsernameChange}/> <br/>
密码: <input type="password" name="password" value={password} onChange={this.onPasswordChange}/> <br/>
<input type="submit" value="登录"/>
</form>
</div>
)
}
}
复制代码
// 受控组件
class Register extends Component {
state = {
username: '',
password: '',
rePassword: ''
}
onUsernameChange = (e) => {
this.setState({username: e.target.value});
}
onPasswordChange = (e) => {
this.setState({password: e.target.value});
}
onRePasswordChange = (e) => {
this.setState({rePassword: e.target.value});
}
register = (e) => {
// 禁止默认事件
e.preventDefault();
// 收集表单数据
const { username, password, rePassword } = this.state;
alert(`用户名: ${username}, 密码: ${password}, 确认密码: ${rePassword}`);
}
render () {
const { username, password, rePassword } = this.state;
return (
<div>
<h2>注册</h2>
<form onSubmit={this.register}>
用户名: <input type="text" name="username" value={username} onChange={this.onUsernameChange}/> <br/>
密码: <input type="password" name="password" value={password} onChange={this.onPasswordChange}/> <br/>
确认密码: <input type="password" name="rePassword" value={rePassword} onChange={this.onRePasswordChange}/> <br/>
<input type="submit" value="注册"/>
</form>
</div>
)
}
}
复制代码
// 咱们以 Register 组件为例来看
class Register extends Component {
state = {
username: '',
password: '',
rePassword: ''
}
// 最终修改状态数据的函数
onChange = (stateName, stateValue) => {
this.setState({[stateName]: stateValue});
}
// 高阶函数 --> 这样后面就能一直复用当前函数,而不用从新建立了~
composeChange = (name) => {
return (e) => this.onChange(name, e.target.value);
}
// 统一全部提交表单函数名
handleSubmit = (e) => {
e.preventDefault();
const { username, password, rePassword } = this.state;
alert(`用户名: ${username}, 密码: ${password}, 确认密码: ${rePassword}`);
}
render () {
const { username, password, rePassword } = this.state;
return (
<div>
<h2>注册</h2>
<form onSubmit={this.handleSubmit}>
用户名: <input type="text" name="username" value={username} onChange={this.composeChange('username')}/> <br/>
密码: <input type="password" name="password" value={password} onChange={this.composeChange('password')}/> <br/>
确认密码: <input type="password" name="rePassword" value={rePassword} onChange={this.composeChange('rePassword')}/> <br/>
<input type="submit" value="注册"/>
</form>
</div>
)
}
}
复制代码
// 高阶组件 withHoc
export default function withHoc(WrappedComponent) {
return class extends Component {
state = {
username: '',
password: '',
rePassword: ''
}
onChange = (stateName, stateValue) => {
this.setState({[stateName]: stateValue});
}
composeChange = (name) => {
return (e) => this.onChange(name, e.target.value);
}
handleSubmit = (e) => {
e.preventDefault();
const { username, password, rePassword } = this.state;
if (rePassword) {
alert(`用户名: ${username}, 密码: ${password}, 确认密码: ${rePassword}`);
} else {
alert(`用户名: ${username}, 密码: ${password}`);
}
}
render () {
// 抽取方法
const mapMethodToProps = {
composeChange: this.composeChange,
handleSubmit: this.handleSubmit,
}
// 将状态数据和操做的方法以 props 的方式传入的包装组件中
return (
<div>
{/*提取公共头部*/}
<h2>xxx</h2>
<WrappedComponent {...this.state} {...mapMethodToProps}/>
</div>
)
}
}
}
// 组件 Register
class Register extends Component {
render () {
const { handleSubmit, composeChange, username, password, rePassword } = this.props;
return (
<form onSubmit={handleSubmit}>
用户名: <input type="text" name="username" value={username} onChange={composeChange('username')}/> <br/>
密码: <input type="password" name="password" value={password} onChange={composeChange('password')}/> <br/>
确认密码: <input type="password" name="rePassword" value={rePassword} onChange={composeChange('rePassword')}/> <br/>
<input type="submit" value="注册"/>
</form>
)
}
}
// 向外暴露的是高阶组件的返回值~包装了 Register 组件返回了一个新组件
export default withHoc(Register);
复制代码
// 再次包裹了一层高阶函数, 这个高阶函数执行后返回值才是高阶组件
// 经过这种方式, 高阶组件内部就能获取参数了~
export default (title) => (WrappedComponent) => {
return class Form extends Component {
...重复代码省略...
render () {
const mapMethodToProps = {
composeChange: this.composeChange,
handleSubmit: this.handleSubmit,
}
return (
<div>
{/*获取到参数值就能正常显示了~*/}
<h2>{title}</h2>
<WrappedComponent {...this.state} {...mapMethodToProps}/>
</div>
)
}
}
}
复制代码
class App extends Component {
render() {
return (
<div>
{/*父组件向子组件传递属性*/}
<Login name="jack" age={18}/>
<Register />
</div>
);
}
}
复制代码
export default (title) => (WrappedComponent) => {
return class Form extends Component {
...重复代码省略...
render () {
const mapMethodToProps = {
composeChange: this.composeChange,
handleSubmit: this.handleSubmit,
}
return (
<div>
{/*获取到参数值就能正常显示了~*/}
<h2>{title}</h2>
{/* 将当前组件接受到的props传给包装组件~*/}
<WrappedComponent {...this.props} {...this.state} {...mapMethodToProps}/>
</div>
)
}
}
}
复制代码
class Login extends Component {
render () {
const { handleSubmit, composeChange, username, password, name, age } = this.props;
return (
<div>
<p>你的名字: {name}</p>
<p>你的年龄: {age}</p>
<form onSubmit={handleSubmit}>
用户名: <input type="text" name="username" value={username} onChange={composeChange('username')}/> <br/>
密码: <input type="password" name="password" value={password} onChange={composeChange('password')}/> <br/>
<input type="submit" value="登录"/>
</form>
</div>
)
}
}
复制代码
export default (title) => (WrappedComponent) => {
return class Form extends Component {
// 定义静态方法,修改组件在调试工具中显示的名称
static displayName = `Form(${getDisplayName(WrappedComponent)})`
...省略重复代码...
}
}
// 获取包装组件的displayName的方法
function getDisplayName(WrappedComponent) {
return WrappedComponent.displayName || WrappedComponent.name || 'Component';
}
复制代码
const { override, addDecoratorsLegacy } = require('customize-cra');
// 修改 create-react-app 的 webpack 的配置
module.exports = override(
addDecoratorsLegacy()
)
复制代码
// 将 react-scripts 修改成 react-app-rewired
"scripts": {
"start": "react-app-rewired start",
"build": "react-app-rewired build",
"test": "react-app-rewired test"
},
复制代码
@withHoc('登录')
class Login extends Component {
...省略重复代码...
}
export default Login;
复制代码
@withHoc('注册')
class Register extends Component {
...省略重复代码...
}
export default Register;
复制代码
重复代码永远是咱们须要考虑处理的代码,因此咱们有模块化、组件化、工具类函数等等, 在 React 中再次引入了一个高阶组件的概念,都是为了去除掉万恶的重复代码,让咱们代码变得更加精简。 本篇文章全部源码都放在了 git仓库,若是它对你有帮助的话,欢迎点 star ~~react