为了提高代码的复用在react中我们可以使用高阶组件

1.添加高阶组件

高阶组件主要代码模板HOC.js

export default (WrappedComponent) => {
return class extends Component {
constructor(props) {
super(props)
this.state = { //定义可复用的状态 }
this.getCode = this.getCode.bind(this)
} componentWillMount() { }
    //定义可复用的方法
getCode(mobile) {
...
}
postVcode(mobile) {
...
}
render() {
return (
<div>
<WrappedComponent getCode={this.getCode} state={this.state} {...this.props}/>
</div>
)
}
}
}

注:其中<WrappedComponent />的自定义属性getCode与state传递了对外可以用的方法与属性

2.在其他组件中使用高阶组件

register.js

import HOC from 'common/js/HOC'
class Register extends Component{
  ...
  ...
}
export default HOC(Register)

或者也可以使用装饰器语法书写

import HOC from 'common/js/HOC'
@HOC
class Register extends Component{
...
}
export default Register

3.完整示例代码

例如 发送短信验证码功能在注册于忘记密码2个组件中都用到了,我们可以把它抽离到HOC中

HOC.js

import React, {Component} from 'react'
import axios from 'axios'
import qs from 'qs'
import { noToken } from './config' import { loadToken } from 'common/js/cache'
import { url } from 'common/js/config'
let token = loadToken()
console.log('token', token);
export default (WrappedComponent) => {
return class extends Component {
constructor(props) {
super(props)
this.state = {
codeBtnText: '发送验证码'
}
this.getCode = this.getCode.bind(this)
this.postVcode = this.postVcode.bind(this)
}
componentWillMount() { }
getCode(mobile) {
if (mobile === '') {
this.setState({
tipsText: '请输入手机号码'
})
this.refs.confirm.show()
return
}
if (!/1[3|4|5|7|8]\d{9}/.test(mobile)) {
this.setState({
tipsText: '请输入正确手机号码'
})
this.refs.confirm.show()
return
}
this.codeBtnDisable = true
// console.log(this.codeBtnDisable)
this.postVcode(mobile)
let total = 59
this.setState({codeBtnText: `${total}秒`})
// this.codeBtnText = `${total}秒`
this.timer = setInterval(() => {
// console.log(total)
--total
// this.codeBtnText = `${total}秒`
this.setState({codeBtnText: `${total}秒`})
if (total <= 0) {
clearInterval(this.timer)
// this.codeBtnText = '发送验证码'
this.setState({codeBtnText: `发送验证码`})
this.codeBtnDisable = false
}
}, 1000)
}
postVcode(mobile) {
var _params = {
Phone: mobile
}
var that = this
axios({ method: 'post',
url: url + 'ComService/PostVcode',
data: _params
})
.then(function (res) {
if (res.data.issuccess) {
that.setState({
tipsText: res.data.message
})
that.refs.confirm.show()
//that.saveUserApplyStepList(res.data.result)
} else {
that.setState({
tipsText: res.data.message
})
that.refs.confirm.show()
that.codeBtnDisable = false
clearInterval(that.timer)
// that.codeBtnText = `发送验证码`
this.setState({codeBtnText: `发送验证码`})
return false
}
})
.catch(function (error) {
console.log(error)
})
}
render() {
return (
<div>
<WrappedComponent getCode={this.getCode} state={this.state} {...this.props}/>
</div>
)
}
}
}

register.js

import React, {Component} from 'react'
import axios from 'common/js/http'
import { url } from 'common/js/config'
import Confirm from 'base/confirm/confirm'
import { withRouter } from 'react-router-dom'
import { setToken } from 'common/js/cache'
import getCodeHOC from 'common/js/HOC'
@getCodeHOC
class Register extends Component{ constructor() {
super()
this.state = {
mobile: '',
password: '',
tipsText: '',
isOpen: false,
inputType: 'password',
codeBtnText: '发送验证码'
}
this.confirm = React.createRef()
this.buttonBtn = React.createRef()
this.handleMobileChange = this.handleMobileChange.bind(this)
this.handlePassWordChange = this.handlePassWordChange.bind(this)
this.handleLogin = this.handleLogin.bind(this)
this.switchEye = this.switchEye.bind(this)
this.goToLogin = this.goToLogin.bind(this)
// this.getCode = this.getCode.bind(this)
this.btnDisable = false
this.codeBtnDisable = false
// this.codeBtnText = '发送验证码'
this.timer = null
}
componentDidMount() {
let _mobile = localStorage.getItem('mobile')
this.setState({
mobile: _mobile
})
}
handleMobileChange (e) {
this.setState({
mobile: e.target.value
})
}
handleLogin (e) {
let that = this
let params = {
Identifier:this.state.mobile,
Credential:this.state.password
}
if (params.Identifier === '') {
this.setState({
tipsText:'请输入手机号码'
})
this.refs.confirm.show()
return
}
if (!/1[3|4|5|7|8]\d{9}/.test(params.Identifier)) {
this.setState({
tipsText:'请输入正确手机号码'
})
this.refs.confirm.show()
return
}
if (params.Credential === '') {
this.setState({
tipsText:'请输入密码'
})
this.refs.confirm.show()
return false
}
axios({ method: 'post',
url: url + 'Login/UserLogin',
data: params
}).then((res) => {
// console.log(res);
if (res.data.issuccess) {
console.log(that.props);
window.location.href = '/home'
setToken(res.data.result.Token)
localStorage.setItem('mobile', that.state.mobile)
} else {
that.setState({
tipsText: res.data.message
})
that.refs.confirm.show()
}
})
}
handlePassWordChange(e) {
this.setState({
password: e.target.value
})
}
switchEye () {
this.setState(prevState => ({
isOpen: !prevState.isOpen
}), ()=> {
this.state.isOpen ? this.setState({inputType: 'text'}) : this.setState({inputType: 'password'})
})
}
shouldComponentUpdate(nextProps, nextState) {
// console.log('nextProps', nextProps);
console.log('nextState', nextState);
if (nextState.mobile && (/1[3|4|5|7|8]\d{9}/.test(nextState.mobile)) && nextState.password ) {
this.btnDisable = true
} else {
this.btnDisable = false
}
if (nextState.codeBtnText === '发送验证码') {
this.codeBtnDisable = false
}
return true
}
goToLogin () {
console.log(this.props);
this.props.history.push('/login')
}
render() {
return (
<div>
<div className="title">用户注册</div>
<div className="inputBox padType">
<div className="input size-0 align-1">
<label >手机号</label>
<input type="tel" placeholder="请输入手机号" maxLength="11" value={this.state.mobile} onChange={this.handleMobileChange} />
</div>
</div>
<div className="inputBox padType">
<div className="input size-0 align-1">
<label >验证码</label>
<input placeholder="请输入密码" maxLength="6" type="number"/> <div className={"send-smg-code " + (this.codeBtnDisable ? 'disable' : '')} onClick={()=>this.props.getCode(this.state.mobile)}>{this.props.state.codeBtnText}</div>
</div>
</div>
<div className="inputBox padType">
<div className="input size-0 align-1">
<label >密&nbsp;&nbsp;&nbsp;&nbsp;码</label>
<input placeholder="请输入密码" maxLength="16" type={this.state.inputType} onChange={this.handlePassWordChange}/>
<div className="eye" onClick={this.switchEye}>
</div>
</div>
</div>
<div className="agree-register">
<div className="agree-check"></div> <div className="agree-text">
同意《
<a href="#/useAgreementRegister">
注册协议
</a>

</div>
</div>
<div className="buttonBox disable">
<div className={"button " + (this.btnDisable ? '' : 'disable')}>
注册
</div>
</div>
<div className="child-mt20"> <div className="buttonBox reverse">
<div className="button reverse" onClick={this.goToLogin}>
已有账号,去登录
</div>
</div>
</div>
<Confirm text={this.state.tipsText} confirmType='2' ref="confirm"></Confirm>
</div>
)
} }
export default withRouter(Register)

forgetpassword.js

import React, {Component} from 'react'
import axios from 'common/js/http'
import { url } from 'common/js/config'
import Confirm from 'base/confirm/confirm'
import { withRouter } from 'react-router-dom'
import { setToken } from 'common/js/cache'
import HOC from 'common/js/HOC'
// @HOC
class Forgetpassword extends Component{
constructor() {
super()
this.state = {
mobile: '',
password: '',
tipsText: '',
isOpen: false,
inputType: 'password',
codeBtnText: '发送验证码'
}
this.confirm = React.createRef()
this.buttonBtn = React.createRef()
this.handleMobileChange = this.handleMobileChange.bind(this)
this.handlePassWordChange = this.handlePassWordChange.bind(this)
this.handleLogin = this.handleLogin.bind(this)
this.switchEye = this.switchEye.bind(this)
// this.getCode = this.getCode.bind(this)
this.btnDisable = false
this.codeBtnDisable = false
// this.codeBtnText = '发送验证码'
this.timer = null
}
componentDidMount() {
let _mobile = localStorage.getItem('mobile')
this.setState({
mobile: _mobile
})
}
handleMobileChange (e) {
this.setState({
mobile: e.target.value
})
} handleLogin (e) {
let that = this
let params = {
Identifier:this.state.mobile,
Credential:this.state.password
}
if (params.Identifier === '') {
this.setState({
tipsText:'请输入手机号码'
})
this.refs.confirm.show()
return
}
if (!/1[3|4|5|7|8]\d{9}/.test(params.Identifier)) {
this.setState({
tipsText:'请输入正确手机号码'
})
this.refs.confirm.show()
return
}
if (params.Credential === '') {
this.setState({
tipsText:'请输入密码'
})
this.refs.confirm.show()
return false
}
axios({ method: 'post',
url: url + 'Login/UserLogin',
data: params
}).then((res) => {
// console.log(res);
if (res.data.issuccess) {
console.log(that.props);
// window.location.href = '/home'
let _href = window.location.href
let _hrefArr = _href.split('#')
window.location.href = _hrefArr[0] + '#/home'; //太low了。。。。
setToken(res.data.result.Token)
localStorage.setItem('mobile', that.state.mobile)
} else {
that.setState({
tipsText: res.data.message
})
that.refs.confirm.show()
}
})
}
handlePassWordChange(e) {
this.setState({
password: e.target.value
})
}
switchEye () {
this.setState(prevState => ({
isOpen: !prevState.isOpen
}), ()=> {
this.state.isOpen ? this.setState({inputType: 'text'}) : this.setState({inputType: 'password'})
})
}
shouldComponentUpdate(nextProps, nextState) {
// console.log('nextProps', nextProps);
console.log('nextState', nextState);
if (nextState.mobile && (/1[3|4|5|7|8]\d{9}/.test(nextState.mobile)) && nextState.password ) {
this.btnDisable = true
} else {
this.btnDisable = false
}
if (nextState.codeBtnText === '发送验证码') {
this.codeBtnDisable = false
}
return true
}
render() {
return (
<div>
<div className="title">忘记密码</div>
<div className="inputBox padType">
<div className="input size-0 align-1">
<label >手机号</label>
<input type="tel" placeholder="请输入手机号" maxLength="11" value={this.state.mobile} onChange={this.handleMobileChange}/>
</div>
</div>
<div className="inputBox padType">
<div className="input size-0 align-1">
<label >验证码</label>
<input placeholder="请输入密码" maxLength="6" type="number"/>
<div className={'send-smg-code ' + (this.codeBtnDisable ? 'disable' : '')} onClick={(e) => this.props.getCode(this.state.mobile)}>{this.props.state.codeBtnText}</div>
</div>
</div>
<div className="inputBox padType">
<div className="input size-0 align-1">
<label >新密码</label>
<input placeholder="请输入密码" maxLength="16" type={this.state.inputType} onChange={this.handlePassWordChange}/>
<div className={ 'eye ' + (this.state.isOpen ? 'open' : '')} onClick={this.switchEye}></div>
</div>
</div>
<div className="buttonBox ">
<div className={'button ' + (this.btnDisable ? '': "disable")} ref={this.buttonBtn} onClick={this.handleLogin}>
确定
</div>
</div> <Confirm text={this.state.tipsText} confirmType='2' ref="confirm"></Confirm>
</div>
)
}
}
export default withRouter(HOC(Forgetpassword))

4.注意点

一、使用装饰器语法需要安装transform-decorators-legacy插件并配置package

1.npm install babel-plugin-transform-decorators-legacy --save-dev

2.配置package中babel下plugin

 "babel": {
"presets": [
"react-app"
],
"plugins": ["transform-decorators-legacy"]
},

二、高阶组件中的复用方法或状态属性需要在其他组件中使用记得作为属性传递出去,以便其他组件使用

react高阶组件的使用的更多相关文章

  1. 聊聊React高阶组件(Higher-Order Components)

    使用 react已经有不短的时间了,最近看到关于 react高阶组件的一篇文章,看了之后顿时眼前一亮,对于我这种还在新手村晃荡.一切朝着打怪升级看齐的小喽啰来说,像这种难度不是太高同时门槛也不是那么低 ...

  2. 当初要是看了这篇,React高阶组件早会了

    当初要是看了这篇,React高阶组件早会了. 概况: 什么是高阶组件? 高阶部件是一种用于复用组件逻辑的高级技术,它并不是 React API的一部分,而是从React 演化而来的一种模式. 具体地说 ...

  3. react高阶组件的理解

    [高阶组件和函数式编程] function hello() { console.log('hello jason'); } function WrapperHello(fn) { return fun ...

  4. 函数式编程与React高阶组件

    相信不少看过一些框架或者是类库的人都有印象,一个函数叫什么creator或者是什么什么createToFuntion,总是接收一个函数,来返回另一个函数.这是一个高阶函数,它可以接收函数可以当参数,也 ...

  5. React高阶组件学习笔记

    高阶函数的基本概念: 函数可以作为参数被传递,函数可以作为函数值输出. 高阶组件基本概念: 高阶组件就说接受一个组件作为参数,并返回一个新组件的函数. 为什么需要高阶组件 多个组件都需要某个相同的功能 ...

  6. 利用 React 高阶组件实现一个面包屑导航

    什么是 React 高阶组件 React 高阶组件就是以高阶函数的方式包裹需要修饰的 React 组件,并返回处理完成后的 React 组件.React 高阶组件在 React 生态中使用的非常频繁, ...

  7. react高阶组件的一些运用

    今天学习了react高阶组件,刚接触react学习起来还是比较困难,和大家分享一下今天学习的知识吧,另外缺少的地方欢迎补充哈哈 高阶组件(Higher Order Components,简称:HOC) ...

  8. React——高阶组件

    1.在React中higher-order component (HOC)是一种重用组件逻辑的高级技术.HOC不是React API中的一部分.HOC是一个函数,该函数接收一个组件并且返回一个新组件. ...

  9. react 高阶组件的 理解和应用

    高阶组件是什么东西 简单的理解是:一个包装了另一个基础组件的组件.(相对高阶组件来说,我习惯把被包装的组件称为基础组件) 注意:这里说的是包装,可以理解成包裹和组装: 具体的是高阶组件的两种形式吧: ...

随机推荐

  1. ios9 safari currentTime audio bug

    var audio = document.createElement('audio') audio.src = 'https://ic-static.vipkidteachers.com/course ...

  2. poj 2155 matrix 二维线段树 线段树套线段树

    题意 一个$n*n$矩阵,初始全为0,每次翻转一个子矩阵,然后单点查找 题解 任意一种能维护二维平面的数据结构都可以 我这里写的是二维线段树,因为四分树的写法复杂度可能会退化,因此考虑用树套树实现二维 ...

  3. 【原创】大数据基础之Zookeeper(4)应用场景

    1 集群配置管理 应用服务器的配置通常会放到properties文件中,格式为: system1.module2.prop3=value4 然后启动的时候加载,这样带来的问题是启动后无法修改,想修改必 ...

  4. C++入门篇一

    双冒号(::)的作用:作用域运算符,全局作用域 void LOL::game1(){//在LOL命名空间下面的game1 cout << "LOL游戏开始" <& ...

  5. php 两变量值互换 方法

    //方法一:$a ="abc";$b="def"; $a = $a^$b;$b = $b^$a;$a = $a^$b; //方法二:list($a, $b)= ...

  6. Django-DRF-图书增删改查 !!!

      自己封装的 class MyResponse(): def __init__(self): self.status = 100 self.msg = None @property def get_ ...

  7. Debian Jessie升级至Stretch小记

    昨天Debian Stretch正式发布.为了尝新,昨天晚上便从Jessie升到了Stretch.结果,早上起来发现系统已无法进入X视窗环境,且NVIDIA的官方驱动无法成功编译和安装.看来,每次系统 ...

  8. SQL数据库分页OFFSET FETCH NEXT

    SELECT * FROM dbo.UMS_System_Menu AS USM ORDER BY USM.MenuCode OFFSET ROW --跳过前10条 ROW ONLY --取20条

  9. [转] Vue + Webpack 组件式开发(练习环境)

    前言 研究了下别人的 vue 多页面框架, 都是直接复制 package.json 文件,然后在本地 npm install 一下即可, 或者使用官网 vue-cli 工具生成一个项目, 觉得这样虽然 ...

  10. Datatables插件1.10.15版本服务器处理模式ajax获取分页数据实例解析

    一.问题描述 前端需要使用表格来展示数据,找了一些插件,最后确定使用dataTables组件来做. 后端的分页接口已经写好了,不能修改.接口需要传入页码(pageNumber)和页面显示数据条数(pa ...