成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

從零開始學(xué)習(xí) React 高階組件

_Dreams / 1973人閱讀

01、介紹

React 高階組件也叫做 React HOC(High Order Component), 它是react中的高級技術(shù), 用來重用組件邏輯。

但高階組件本身并不是React API。它只是一種模式,這種模式是由react自身的組合性質(zhì)必然產(chǎn)生的。

那么在學(xué)習(xí)高階組件之前有一個(gè)概念我們必須清楚,就是高階函數(shù)。

02、高階函數(shù)

概念:高階函數(shù)是一個(gè)函數(shù),它接收函數(shù)作為參數(shù)或?qū)⒑瘮?shù)作為輸出返回

舉個(gè)栗子:

接收函數(shù)作為參數(shù)

function a(x) {
  x();
}
function b() {
  alert("hello");
}

a(b);

將函數(shù)作為輸出返回

function a() {
  function b() {
    alert("hello");
  }
  return b;
}

a()();

以上函數(shù)a就是一個(gè)高階函數(shù), 用法非常簡單, 那么實(shí)際開發(fā)中又有哪些是高階函數(shù)呢?

Array 的 map 、reduce 、filter 等方法

Object 的 keys 、values 等方法

03、高階組件

概念:高階組件就是一個(gè)函數(shù),且該函數(shù)接受一個(gè)組件作為參數(shù),并返回一個(gè)新的組件

舉個(gè)栗子:

// WrappedComponent 就是傳入的包裝組件
function withHoc(WrappedComponent) {
  return class extends Component {
    render () {
      return (
        
      )
    }
  }
}

withHoc 函數(shù)就是一個(gè)高階組件。那么高階組件到底有什么神奇的魔力,值得我們?yōu)橹裕?/p>

開發(fā)組件時(shí),我們會(huì)遇到相同的功能,使用高階組件則能減少重復(fù)代碼

04、高階組件實(shí)訓(xùn)1

目的: 定義高階組件

組件 Login -- 登陸頁面

// 受控組件
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) => {
    // 禁止默認(rèn)事件
    e.preventDefault();
    // 收集表單數(shù)據(jù)
    const { username, password } = this.state;
    alert(`用戶名: ${username}, 密碼: ${password}`);
  }
  
  render () {
    const { username, password } = this.state;
    return (
      

登陸

用戶名:
密碼:
) } }

組件 Register -- 注冊頁面

// 受控組件
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) => {
    // 禁止默認(rèn)事件
    e.preventDefault();
    // 收集表單數(shù)據(jù)
    const { username, password, rePassword } = this.state;
    alert(`用戶名: ${username}, 密碼: ${password}, 確認(rèn)密碼: ${rePassword}`);
  }
  
  render () {
    const { username, password, rePassword } = this.state;
    return (
      

注冊

用戶名:
密碼:
確認(rèn)密碼:
) } }

頁面效果

我們發(fā)現(xiàn)里面重復(fù)邏輯實(shí)在太多了,尤其是 onXxxChange 函數(shù)出現(xiàn)太多,我們先優(yōu)化一下。

// 我們以 Register 組件為例來看
class Register extends Component {
  state = {
    username: "",
    password: "",
    rePassword: ""
  }
  // 最終修改狀態(tài)數(shù)據(jù)的函數(shù)
  onChange = (stateName, stateValue) => {
    this.setState({[stateName]: stateValue});
  }
  // 高階函數(shù) --> 這樣后面就能一直復(fù)用當(dāng)前函數(shù),而不用重新創(chuàng)建了~
  composeChange = (name) => {
    return (e) => this.onChange(name, e.target.value);
  }
  // 統(tǒng)一所有提交表單函數(shù)名
  handleSubmit = (e) => {
    e.preventDefault();
    const { username, password, rePassword } = this.state;
    alert(`用戶名: ${username}, 密碼: ${password}, 確認(rèn)密碼: ${rePassword}`);
  }
  
  render () {
    const { username, password, rePassword } = this.state;
    return (
      

注冊

用戶名:
密碼:
確認(rèn)密碼:
) } }

現(xiàn)在兩個(gè)頁面都有 onChange 、 composeChange 、handleSubmit 函數(shù)和相關(guān)的狀態(tài),我們接下來提取,封裝成高階組件!

// 高階組件 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}, 確認(rèn)密碼: ${rePassword}`);
      } else {
        alert(`用戶名: ${username}, 密碼: ${password}`);
      }
    }
    
    render () {
      // 抽取方法
      const mapMethodToProps = {
        composeChange: this.composeChange,
        handleSubmit: this.handleSubmit,
      }
      // 將狀態(tài)數(shù)據(jù)和操作的方法以 props 的方式傳入的包裝組件中
      return (
        
{/*提取公共頭部*/}

xxx

) } } } // 組件 Register class Register extends Component { render () { const { handleSubmit, composeChange, username, password, rePassword } = this.props; return (
用戶名:
密碼:
確認(rèn)密碼:
) } } // 向外暴露的是高階組件的返回值~包裝了 Register 組件返回了一個(gè)新組件 export default withHoc(Register);

現(xiàn)在我們提取了公共方法、狀態(tài)等數(shù)據(jù), 封裝了一個(gè)基本的高階組件。 但是還有很多需要問題需要解決,現(xiàn)在開始行動(dòng)~

05、高階組件實(shí)訓(xùn)2

目的: 向高階組件中傳參

修改高階組件

// 再次包裹了一層高階函數(shù), 這個(gè)高階函數(shù)執(zhí)行后返回值才是高階組件
// 通過這種方式, 高階組件內(nèi)部就能獲取參數(shù)了~
export default (title) => (WrappedComponent) => {
  return class Form extends Component {
    ...重復(fù)代碼省略...
    
    render () {
      const mapMethodToProps = {
        composeChange: this.composeChange,
        handleSubmit: this.handleSubmit,
      }
      return (
        
{/*獲取到參數(shù)值就能正常顯示了~*/}

{title}

) } } }

在 Login / Register 組件中使用

export default withHoc("登陸")(Login);

export default withHoc("注冊")(Register);

06、高階組件實(shí)訓(xùn)3

目的: 獲取父組件傳遞的 props

修改 App 組件

class App extends Component {
  render() {
    return (
      
{/*父組件向子組件傳遞屬性*/}
); } }

修改高階組件

export default (title) => (WrappedComponent) => {
  return class Form extends Component {
    ...重復(fù)代碼省略...
    
    render () {
      const mapMethodToProps = {
        composeChange: this.composeChange,
        handleSubmit: this.handleSubmit,
      }
      return (
        
{/*獲取到參數(shù)值就能正常顯示了~*/}

{title}

{/* 將當(dāng)前組件接受到的props傳給包裝組件~*/}
) } } }

Login 組件中使用

 class Login extends Component {
   render () {
     const { handleSubmit, composeChange, username, password, name, age } = this.props;
     return (
       

你的名字: {name}

你的年齡: {age}

用戶名:
密碼:
) } }

07、高階組件實(shí)訓(xùn)4

目的: 修改在 React-devtool 中高階組件名稱,方便調(diào)試

修改高階組件

export default (title) => (WrappedComponent) => {
  return class Form extends Component {
    // 定義靜態(tài)方法,修改組件在調(diào)試工具中顯示的名稱
    static displayName = `Form(${getDisplayName(WrappedComponent)})`
    
    ...省略重復(fù)代碼...
  }
}
// 獲取包裝組件的displayName的方法
function getDisplayName(WrappedComponent) {
  return WrappedComponent.displayName || WrappedComponent.name || "Component";
}

修改之前名稱

修改之后名稱

08、使用裝飾器

目的: 簡化使用高階組件

下載包

npm i react-app-rewired customize-cra @babel/plugin-proposal-decorators -D

在項(xiàng)目根目錄配置 config-overrides.js

const { override, addDecoratorsLegacy } = require("customize-cra");
// 修改 create-react-app 的 webpack 的配置
module.exports = override(
  addDecoratorsLegacy()
)

修改 package.json 的 scripts

// 將 react-scripts 修改為 react-app-rewired
"scripts": {
  "start": "react-app-rewired start",
  "build": "react-app-rewired build",
  "test": "react-app-rewired test"
},

以上就是使用 decorator 的配置,修改完后就能使用了~

修改 Login 組件

@withHoc("登陸")
class Login extends Component {
  ...省略重復(fù)代碼...
}
export default Login;

修改 Register 組件

@withHoc("注冊")
class Register extends Component {
  ...省略重復(fù)代碼...
}
export default Register;

react-app-rewired customize-cra 是 create-react-app 2.0以上專門用來修改 webpack 的配置

decorator 還能做很多事,感興趣朋友可以看看 阮一峰ES6教程 了解更多

重復(fù)代碼永遠(yuǎn)是我們需要考慮處理的代碼,所以我們有模塊化、組件化、工具類函數(shù)等等,
在 React 中再次引入了一個(gè)高階組件的概念,都是為了去除掉萬惡的重復(fù)代碼,讓我們代碼變得更加精簡。
本篇文章所有源碼都放在了 git倉庫,如果它對你有幫助的話,歡迎點(diǎn) star ~~

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/102900.html

相關(guān)文章

  • 從零開始編寫React-Express單頁博客應(yīng)用(學(xué)習(xí)總結(jié))

    摘要:單頁博客應(yīng)用編寫總結(jié)很久之前就想寫一個(gè)博客應(yīng)用在一開始想要直接用和模板直接寫但是暑假一開始的時(shí)候不小心入了的坑所以就一不做二不休直接用寫那既然用了不寫個(gè)單頁應(yīng)用也過意不去了不前前后后寫了將近兩個(gè)星期現(xiàn)在看來這其實(shí)是一個(gè)很容易的應(yīng)用但是鑒于 React-Express單頁博客應(yīng)用編寫總結(jié) 很久之前就想寫一個(gè)博客應(yīng)用.在一開始想要直接用express和ejs模板直接寫, 但是暑假一開始的時(shí)...

    Jioby 評論0 收藏0
  • 寫一本關(guān)于 React.js 的小書

    摘要:因?yàn)楣ぷ髦幸恢痹谑褂茫惨恢币詠硐肟偨Y(jié)一下自己關(guān)于的一些知識經(jīng)驗(yàn)。于是把一些想法慢慢整理書寫下來,做成一本開源免費(fèi)專業(yè)簡單的入門級別的小書,提供給社區(qū)。本書的后續(xù)可能會(huì)做成視頻版本,敬請期待。本作品采用署名禁止演繹國際許可協(xié)議進(jìn)行許可 React.js 小書 本文作者:胡子大哈本文原文:React.js 小書 轉(zhuǎn)載請注明出處,保留原文鏈接以及作者信息 在線閱讀:http://huzi...

    Scorpion 評論0 收藏0
  • 前端每周清單半年盤點(diǎn)之 ReactReactNative 篇

    摘要:前端每周清單半年盤點(diǎn)之與篇前端每周清單專注前端領(lǐng)域內(nèi)容,以對外文資料的搜集為主,幫助開發(fā)者了解一周前端熱點(diǎn)分為新聞熱點(diǎn)開發(fā)教程工程實(shí)踐深度閱讀開源項(xiàng)目巔峰人生等欄目。與求同存異近日,宣布將的構(gòu)建工具由遷移到,引發(fā)了很多開發(fā)者的討論。 前端每周清單半年盤點(diǎn)之 React 與 ReactNative 篇 前端每周清單專注前端領(lǐng)域內(nèi)容,以對外文資料的搜集為主,幫助開發(fā)者了解一周前端熱點(diǎn);分為...

    Barry_Ng 評論0 收藏0
  • Vue.js最佳實(shí)踐(五招讓你成為Vue.js大師)

    摘要:但如果你想更加高效地使用來開發(fā),成為大師,那下面我要傳授的這五招你一定得認(rèn)真學(xué)習(xí)一下了。雖然損失了一丟丟性能,但避免了無限的。所以我們需要設(shè)置,這些默認(rèn)行為將會(huì)被去掉以上兩點(diǎn)的優(yōu)化才能成功。陸續(xù)可能還會(huì)更新一些別的招數(shù),敬請期待。 本文面向?qū)ο笫怯幸欢╒ue.js編程經(jīng)驗(yàn)的開發(fā)者。如果有人需要Vue.js入門系列的文章可以在評論區(qū)告訴我,有空就給你們寫。 對大部分人來說,掌握Vue.j...

    CocoaChina 評論0 收藏0

發(fā)表評論

0條評論

最新活動(dòng)
閱讀需要支付1元查看
<