react高阶组件的使用
为了提高代码的复用在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 >密 码</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高阶组件的使用的更多相关文章
- 聊聊React高阶组件(Higher-Order Components)
使用 react已经有不短的时间了,最近看到关于 react高阶组件的一篇文章,看了之后顿时眼前一亮,对于我这种还在新手村晃荡.一切朝着打怪升级看齐的小喽啰来说,像这种难度不是太高同时门槛也不是那么低 ...
- 当初要是看了这篇,React高阶组件早会了
当初要是看了这篇,React高阶组件早会了. 概况: 什么是高阶组件? 高阶部件是一种用于复用组件逻辑的高级技术,它并不是 React API的一部分,而是从React 演化而来的一种模式. 具体地说 ...
- react高阶组件的理解
[高阶组件和函数式编程] function hello() { console.log('hello jason'); } function WrapperHello(fn) { return fun ...
- 函数式编程与React高阶组件
相信不少看过一些框架或者是类库的人都有印象,一个函数叫什么creator或者是什么什么createToFuntion,总是接收一个函数,来返回另一个函数.这是一个高阶函数,它可以接收函数可以当参数,也 ...
- React高阶组件学习笔记
高阶函数的基本概念: 函数可以作为参数被传递,函数可以作为函数值输出. 高阶组件基本概念: 高阶组件就说接受一个组件作为参数,并返回一个新组件的函数. 为什么需要高阶组件 多个组件都需要某个相同的功能 ...
- 利用 React 高阶组件实现一个面包屑导航
什么是 React 高阶组件 React 高阶组件就是以高阶函数的方式包裹需要修饰的 React 组件,并返回处理完成后的 React 组件.React 高阶组件在 React 生态中使用的非常频繁, ...
- react高阶组件的一些运用
今天学习了react高阶组件,刚接触react学习起来还是比较困难,和大家分享一下今天学习的知识吧,另外缺少的地方欢迎补充哈哈 高阶组件(Higher Order Components,简称:HOC) ...
- React——高阶组件
1.在React中higher-order component (HOC)是一种重用组件逻辑的高级技术.HOC不是React API中的一部分.HOC是一个函数,该函数接收一个组件并且返回一个新组件. ...
- react 高阶组件的 理解和应用
高阶组件是什么东西 简单的理解是:一个包装了另一个基础组件的组件.(相对高阶组件来说,我习惯把被包装的组件称为基础组件) 注意:这里说的是包装,可以理解成包裹和组装: 具体的是高阶组件的两种形式吧: ...
随机推荐
- Hibernate查询返回自定义VO的两种方式
说明:createQuery用的hql语句进行查询,createSQLQuery用sql语句查询: 前者以hibernate生成的Bean为对象装入list返回:后者则是以对象数组进行存储: 一.通过 ...
- C语言经典题目
回顾一下吧: 一. 有1.2.3.4个数字,能组成多少个互不相同且无重复数字的三位数?都是多少? 解析:可填在百位.十位.个位的数字都是1.2.3.4.组成所有的排列后再去 掉不满足条件的排列. 常规 ...
- Pygal之世界地图绘制from pygal.i18n import COUNTRIES 报错的解决办法
在<Python编程:从入门到实践>书中的一个项目用到pygal.i18n获取国别码, 问题描述: 在学习<python编程:从入门到精通>的pygal绘制世界地图时,遇到了这 ...
- angular 2+ 变化检测系列二(检测策略)
我们将创建一个简单的MovieApp来显示有关一部电影的信息.这个应用程序将只包含两个组件:显示有关电影的信息的MovieComponent和包含执行某些操作按钮的电影引用的AppComponent. ...
- IP网际协议
IP分类 IP地址分为网络号和主机号,5类不同的IP地址格式如下: A类地址每个网段内最多有224个,也就是16,777,214个. B类地址每个网段内最多有216个,也就是65535个. C类地址每 ...
- vue中mint-ui的filed的与blur事件结合实现检查用户输入是否正确
标题mint-ui的filed与blur事件验证用户输入格式是否正确说明:本人前端菜鸟,只是想借个地方做个笔记,为了以后查阅时比较方便.如有大神有什么建议的地方,欢迎提出来. 1.不得不说,mint- ...
- 后端for循环补充
我们的for循环里面,在外面可以调用它最后一次循环的值,pycharm尽管会飘黄色,但是系统是可以识别出来的,能够调用,而且是循环最后一次的值
- Linux 解压命令tar
1. 参数说明: -c :建立一个打包文件: -x :解开一个打包文件: -t :查看 tar包里面的文件: (c/x/t仅能存在一个,不可同时存在,因为不可能同时压缩与解压缩.) -z :打包后用g ...
- LOJ.2864.[IOI2018]排座位(线段树)
LOJ 洛谷 先令编号从\(1\)开始.我们要求\([1,i]\)这些数字能否构成一个矩形. 考虑能否用线段树维护,让每个叶子节点\(i\)表示前\(i\)个数能否构成矩形. 一种方法是维护前\(i\ ...
- 浅析uWSGI、uwsgi、wsgi
WSGI协议 首先弄清下面几个概念: WSGI:全称是Web Server Gateway Interface,WSGI不是服务器,python模块,框架,API或者任何软件,只是一种规范,描述web ...