題圖 From Bing By Clmjavascript
今天跟你們聊一聊React的高階組件,那麼什麼是高階組件呢?
java
若是一個函數 接受一個或多個組件做爲參數而且返回一個組件 就可稱之爲 高階組件。node
高階組件的本質就是一個函數,這個函數的參數是組件,這個函數的返回結果是一個組件。react
咱們用一個案例來講明,封裝一個Mouse組件,這個組件實時獲取鼠標的座標並實時顯示出來。微信
代碼以下:dom
import React,{Component} from 'react';class Mouse extends Component { constructor(props) { super(props); this.state = { x:0, y:0 } } handleMouse=(e)=>{ this.setState({ x:e.clientX, y:e.clientY }) } render() { return <div onMouseMove={this.handleMouse} style={{ background:"red", height:"100px", width:"500px", }} > <h1>x:{this.state.x}</h1> <h1>y:{this.state.y}</h1> </div> }}export default Mouse;
顯示結果:
函數
代碼很簡單,在一個div上面監聽鼠標的拖動事件,實時獲取座標,並將其顯示出來,在此基礎之上,咱們將其改形成高階組件。
this
這裏面須要明白幾個問題,爲何要改造呢?如何改造呢?spa
首先來搞清楚第一個問題:假如咱們的項目中有多個組件須要獲取鼠標的座標,有的組件只是顯示,有的組件須要根據座標來移動dom元素,咱們改如何作呢?簡單直白的方法,直接copy上面的代碼,修改代碼,有多少組件須要實時獲取鼠標座標就copy修改幾回。.net
這顯然不是最好方案,咱們能夠將獲取鼠標座標的邏輯抽離出來,構造一個高階組件,那麼如何構造呢?
再次重申一下高階組件的定義:
若是一個函數 接受一個或多個組件做爲參數而且返回一個組件 就可稱之爲 高階組件。
咱們根據這個定義書寫代碼:
// 一、定義一個函數// 二、參數爲組件function HOC(Comp){ //三、調用後,返回一個組件 return class extends Component{ constructor(props) { super(props); } render() { return <div> {/*二、參數爲組件*/} <Comp/> </div> } }}
以上代碼即是高階組件最簡單的代碼結構,下面咱們來填充上面的代碼,首先咱們要明白,高階組件內部返回的組件的通用邏輯是什麼呢?獲取鼠標的移動座標。
代碼進一步完善以下:
import React,{Component} from 'react';
// 一、定義一個函數// 二、參數爲組件function HOC(Comp){ //三、調用後,返回一個組件 return class extends Component{ constructor(props) { super(props); //四、保存鼠標座標位置 this.state = { x:0, y:0 } } //五、鼠標移動獲取新的位置座標 handleMouse =(e)=>{ this.setState({ x:e.clientX, y:e.cclientY }) } render() { return <div onMouseMove={this.setState}> {/*6將獲取到的座標傳遞給目標組件*/} <Comp x={this.state.x} y={this.state.y}/> </div> } }}
閱讀源碼:咱們在高階組件的結構上增長了以下幾個功能,定義state保存鼠標位置,監聽鼠標移動事件獲取新的座標,將座標傳遞給目標組件。
下面咱們完成目標組件,目標組件的做用主要是顯示座標。代碼以下:
class Show extends Component{ constructor(props) { super(props); } render() { return <div> <h2>x:{this.props.x}</h2> <h2>x:{this.props.y}</h2> </div> }}
最終代碼以下:
import React,{Component} from 'react';
// 一、定義一個函數// 二、參數爲組件function HOC(Comp){ //三、調用後,返回一個組件 return class extends Component{ constructor(props) { super(props); //四、保存鼠標座標位置 this.state = { x:0, y:0 } } //五、鼠標移動獲取新的位置座標 handleMouse =(e)=>{ this.setState({ x:e.clientX, y:e.clientY }) } render() { return <div onMouseMove={this.handleMouse}> {/*二、參數爲組件*/} {/*6將獲取到的座標傳遞給目標組件*/} <Comp x={this.state.x} y={this.state.y}/> </div> } }}// 七、目標組件,主要做用是渲染顯示座標class Show extends Component{ constructor(props) { super(props); } render() { return <div> <h2>x:{this.props.x}</h2> <h2>x:{this.props.y}</h2> </div> }}// 八、將目標組件傳遞進入高階組件,獲得組件,此時新組件具備了獲取鼠標座標的能力let NewComponent = HOC(Show);export default NewComponent;
顯示結果:
閱讀最終代碼,咱們發現,在構造目標組件時,這個組件須要接收高階組件獲取的鼠標座標,而獲取座標後咱們將其作簡單展現。
這裏也能夠根據這個座標作一些其餘的功能。好比根據座標移動dom元素,那麼就只須要構造一個新的組件,這個組件接收x,y座標,而後根據座標移動dom元素,最終代碼以下:
import React,{Component} from 'react';// 一、定義一個函數// 二、參數爲組件function HOC(Comp){ //三、調用後,返回一個組件 return class extends Component{ constructor(props) { super(props); //四、保存鼠標座標位置 this.state = { x:0, y:0 } } //五、鼠標移動獲取新的位置座標 handleMouse =(e)=>{ this.setState({ x:e.clientX, y:e.clientY }) } render() { return <div onMouseMove={this.handleMouse}> {/*二、參數爲組件*/} {/*6將獲取到的座標傳遞給目標組件*/} <Comp x={this.state.x} y={this.state.y}/> </div> } }}// 七、定於目標組件,接收x,y座標參數function Move({x,y}){ return <div style={{ height:"100px", width:"100px", background:"yellow" }}> <div style={{ background:"red", height:"10px", width:"10px", position:"absolute", left:x, top:y }} > Move </div> </div>}//八、構造新的組件let NewComponent = HOC(Move);export default NewComponent;
案例完成了,總結一下:
一、高階組件的本質就是一個函數
二、函數的參數爲一個組件,一般這個組件會接收高階組件傳入的參數
三、函數調用後返回一個新的組件
四、高階組件內部主要是將通用的功能邏輯抽離出來
高階組件還有一些不足,好比說高階組件存在組件嵌套的問題,咱們在下篇文章用一種新的方法來代替他。
以上即是高階組件的使用方式,固然高階組件還有好多其餘的用法,若是你有什麼其餘的想法或建議,歡迎留言。
本文分享自微信公衆號 - nodejs全棧開發(geekclass)。
若有侵權,請聯繫 support@oschina.cn 刪除。
本文參與「OSC源創計劃」,歡迎正在閱讀的你也加入,一塊兒分享。