第一章 引導
學習之前要有一定的:es6基礎担敌、js面向對象編程摘盆、react的一些基礎知識
第二章 高階組件介紹
2-1 高階函數
1、高階函數的兩個基本特征
//1.函數可以做為參數被傳遞
setTimeout(function(){
console.log(1)
},1000)
//2.函數可以作為返回值輸出
function student(name){
return function(){
return name
}
}
2徒探、應用場景:
1).高階函數在時間函數的應用
setTimeout()
setInterval()
2).高階函數在ajax中的應用
$.get('/api/api.json',function(){
console.log('獲取成功')
})
3).高階函數在數組中的應用
some()
every()
filter()
map()
forEach()
2-2 高階組件介紹
1、高階組件基本概念(High Order Component,HOC)
高階組件就是:接受一個組件作為參數并返回一個新的組件的函數
高階組件:是一個函數销斟,并不是組件
代碼演示地址:https://gitee.com/sunnyfan/react-hight-order-component.git
git clone https://gitee.com/sunnyfan/react-hight-order-component.git
cd react-hight-order-component
npm install
npm start
代碼截取
//1.組件A是公共組件庐椒,且被定義為一個高階組件(高階函數)
import React, {Component} from 'react';
function A(WrappedComponent) {
return class A extends Component {
render() {
return (
<div className="container">
<div className="header">
<span>提示</span>
<span>X</span>
</div>
<div className="content">
<WrappedComponent></WrappedComponent>
</div>
</div>
);
}
}
}
export default A;
//B組件
import React, {Component} from 'react';
import A from './A';
class B extends Component {
render() {
return (
<div>
B
</div>
);
}
}
export default A(B);
//C組件
import React, {Component} from 'react';
import A from './A';
class C extends Component {
render() {
return (
<div>
c
</div>
);
}
}
export default A(C);
應為A組件是公共組件,在B和C組件中都被使用到了蚂踊,所以可以把A抽離成為公共組件
2约谈、使用場景
多個組件都需要某個相同的功能,使用高階組件減少重復實現
3犁钟、高階組件實例
react-redux中的connect
export default connect(mapStateToProps,mapDispatchToProps)(Header);
第三章 高階組價實現
3-1編寫高階組件
1.實現一個普通組件
2.將普通組件使用函數包裹
//第一步:實現一個普通組件
import React, {Component} from 'react';
class A extends Component {
render() {
return (
<div>
A
</div>
);
}
}
export default A;
//將普通組件使用函數包裹
import React, {Component} from 'react';
function A(WrappedComponent) {
return class A extends Component {
render() {
return (
<div className="container">
<WrappedComponent />
</div>
);
}
}
}
export default A;
3-1使用高階組件
1.higherOrderComponent(WrappedComponent);
2.@higherOrderComponent 通過裝飾器
要想使用裝飾器的用法:那么我們需要對項目進行一些配置
1).開啟webpack配置項
在創(chuàng)建的create-react-app項目中 運行 npm run eject
2).安裝兩個依賴包
npm install babel-preset-stage-2 -D
npm install babel-preset-react-native-stage-0 -D
或者(簡寫如下):
npm install babel-preset-stage-2 babel-preset-react-native-stage-0 -D
3).項目根目錄創(chuàng)建.babelrc配置文件
//.babelrc
{
"presets":["react-native-stage-0/decorator-support"]
}
ps:如果上面出現報錯
Cannot find module 'react-native-stage-0/decorator-suppor
npm install metro-react-native-babel-preset -D
將.babelrc改為
{
"presets": ["module:metro-react-native-babel-preset"],
"plugins": [
["@babel/plugin-proposal-decorators", { "legacy": true }]
]
}
配置好后棱诱,那么怎么在項目中使用@裝飾器來替代寫法呢
import React, {Component} from 'react';
import A from './A';
@A //第二種使用方法:通過裝飾器
class B extends Component {
render() {
return (
<div>
B
</div>
);
}
}
//export default A(B); 第一種使用方法:高階組件的普通使用
export default B //如果上面使用了@A 那么這個地方直接這樣寫即可
第四章高階組件的應用
4-1 高階組件的代理方式
1、代理方式的高階組件
返回的新組件類直接繼承自React.Component類
新組件扮演的角色傳入參數組件的一個代理涝动,在新組件的render函數中迈勋,將被包裹組件渲染出來,除了高階組件自己要做的工作醋粟,其他功能全局轉手給了被包裹的組件
- 操縱prop
- 抽離狀態(tài)
- 訪問ref
- 包裝組件
1.1.操縱props
高階組件是如何向子組件傳遞參數或者值的呢靡菇?
高階組件是如何去除組件當中的屬性或者值的呢?
import React, {Component} from 'react';
function A(WrappedComponent) {
return class A extends Component {
render() {
const {age, ...otherProps} = this.props
return (
<div className="container">
<div className="header">
<span>提示</span>
<span>X</span>
</div>
<div className="content">
<WrappedComponent
name={'張三'}
sex={'男'}
{...otherProps}
/>
</div>
</div>
);
}
}
}
export default A;
通過屬性值 給子組件傳值:age={'18'}
通過結構的方式去除米愿,其他的參數或者屬性:
//這樣就把age的屬性從所有屬性值剔除出去了
const {age, ...otherProps} = this.props;
<WrappedComponent
name={'張三'}
sex={'男'}
{...otherProps}
/>
1.2.訪問ref
//A組件
import React, {Component} from 'react';
function A(WrappedComponent) {
return class A extends Component {
componentDidMount() {
const value = this.refs
console.log(value.getName())
}
render() {
const {age, ...otherProps} = this.props
return (
<div className="container">
<div className="header">
<span>提示</span>
<span>X</span>
</div>
<div className="content">
<WrappedComponent
name={'張三'}
sex={'男'}
{...otherProps}
ref={(value) => this.refs = value}>
</WrappedComponent>
</div>
</div>
);
}
}
}
export default A;
//B組件
import React, {Component} from 'react';
import A from './A';
@A
class B extends Component {
getName() {
return '我是B組件'
}
render() {
const {name, age, sex} = this.props;
return (
<div>
B
</div>
);
}
}
export default B;
1.3 抽取狀態(tài)
//A組件
import React, {Component} from 'react';
function A(WrappedComponent) {
return class A extends Component {
constructor(props) {
super(props);
this.state = {
inputValue: '張三'
}
}
handleChangeValue = (e) => {
const value = e.target.value;
this.setState({
inputValue: value
})
}
render() {
const {age, ...otherProps} = this.props;
const {inputValue} = this.state;
const newProps = {
value: inputValue,
onChange: this.handleChangeValue,
placeholder: '張三'
}
return (
<div className="container">
<div className="header">
<span>提示</span>
<span>X</span>
</div>
<div className="content">
<WrappedComponent
name={'張三'}
sex={'男'}
{...otherProps}
{...newProps}
/>
</div>
</div>
)
;
}
}
}
export default A;
//B組件
import React, {Component} from 'react';
import A from './A';
@A
class B extends Component {
render() {
const {age, sex, ...newProps} = this.props;
return (
<div>
<p>
<label>請輸入我的名字:</label>
<input
type="text"
value={newProps.value}
onChange={newProps.onChange}
placeholder={newProps.placeholder}
/>
</p>
<p>
我的名字:{newProps.value}
</p>
</div>
);
}
}
export default B;
4-2 繼承方式的高階組件
采用繼承關聯作為參數的組件和返回的組件厦凤,假如傳入的組件參數是WrappedComponent,那么返回的組件就直接繼承自WrappedComponent
2.1代理方式的高階組件和繼承方式的高階組件的區(qū)別
- 操作props
- 操作生命周期函數
//組件D 繼承方式的高階組件
import React from 'react';
const modifyPropsHOC = (WrappedComponent) => class NewComponent extends WrappedComponent {
componentWillMount() {
alert('我是在繼承生命周期函數')
}
render() {
const element = super.render();
const newStyle = {
color: element.type === 'div' ? 'red' : 'green'
};
const newProps = {...this.props, style: newStyle};
return React.cloneElement(element, newProps, element.props.children)
}
};
export default modifyPropsHOC
//E組件 繼承D里面一些
import React, {Component} from 'react';
import D from './D';
@D
class E extends Component {
componentWillMount() {
alert('我是原始生命周期函數')
}
render() {
return (
<div>
我是div
</div>
);
}
}
export default E;
ps:我們應該“代理方式”優(yōu)先于“繼承方式”的
所以我們在開發(fā)過程中育苟,盡量是用代理方式的高階組件
4-3高階組件顯示名
通過高階組件中有一個displayName的屬性來顯示的
import React from 'react';
const modifyPropsHOC = (WrappedComponent) => class NewComponent extends WrappedComponent {
static displayName = `NewComponent(${getDisplayName(WrappedComponent)})`; //這里設置組件名稱
render() {
const element = super.render();
const newStyle = {
color: element.type === 'div' ? 'red' : 'green'
};
const newProps = {...this.props, style: newStyle};
return React.cloneElement(element, newProps, element.props.children)
}
};
function getDisplayName(WrappedComponent) {
return WrappedComponent.displayName || WrappedComponent.name || 'Component'
}
export default modifyPropsHOC
第五章 高階組件的實際應用-底部導航切換
代碼地址
git clone https://gitee.com/sunnyfan/react-hight-order-component.git
git checkout feature/shili