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