亚洲激情专区-91九色丨porny丨老师-久久久久久久女国产乱让韩-国产精品午夜小视频观看

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

React中無狀態組件與高階組件的示例分析

發布時間:2021-06-29 15:16:07 來源:億速云 閱讀:137 作者:小新 欄目:web開發

這篇文章主要介紹React中無狀態組件與高階組件的示例分析,文中介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們一定要看完!

無狀態組件(Stateless Component) 是 React 0.14 之后推出的,大大增強了編寫 React 組件的方便性,也提升了整體的渲染性能。

無狀態組件 (Stateless Component)

function HelloComponent(props, /* context */) {
 return <div>Hello {props.name}</div>
}
ReactDOM.render(<HelloComponent name="Sebastian" />, mountNode)

HelloComponent 第一個參數是 props,第二個是 context。最后一句也可以這么寫:

ReactDOM.render(HelloComponent{ name:"Sebastian" }, mountNode)

可以看到,原本需要寫“類”定義(React.createClass 或者 class YourComponent extends React.Component)來創建自己組件的定義,現在被精簡成了只寫一個 render 函數。更值得一提的是,由于僅僅是一個無狀態函數,React 在渲染的時候也省掉了將“組件類” 實例化的過程。

結合 ES6 的解構賦值,可以讓代碼更精簡。例如下面這個 Input 組件:

function Input({ label, name, value, ...props }, { defaultTheme }) {
 const { theme, autoFocus, ...rootProps } = props
 return (
  <label
   htmlFor={name}
   children={label || defaultLabel}
   {...rootProps}
  >
  <input
   name={name}
   type="text"
   value={value || ''}
   theme={theme || defaultTheme}
   {...props}
  />
 )}
Input.contextTypes = {defaultTheme: React.PropTypes.object};

這個 Input 組件(僅僅是示例)直接實現了 label/inputText 的組合:

  1. defaultTheme 是從 Context 中解構出來的,如果 props 沒有設定 theme,就將用 defaultTheme 替代。

  2. autoFocus 需要被傳遞到底層的 inputText 而不能同時遺留給 label,因此會先通過 { theme, autoFocus, ...rootProps } = props 拿出來。

無狀態組件用來實現 Server 端渲染也很方便,只要避免去直接訪問各種 DOM 方法。

無狀態組件與組件的生命周期方法

我們可以看到,無狀態組件就剩了一個 render 方法,因此也就沒有沒法實現組件的生命周期方法,例如 componentDidMount, componentWillUnmount 等。那么如果需要讓我們的 Input 組件能夠響應窗口大小的變化,那么該如何實現呢?這其實還是要引入“有狀態的組件”,只不過這個“有狀態的組件”可以不僅僅為 "Input" 組件服務。

const ExecutionEnvironment = require('react/lib/ExecutionEnvironment')
const defaultViewport = { width: 1366, height: 768 }; // Default size for server-side rendering

function withViewport(ComposedComponent) {
 return class Viewport extends React.Component {
  state = {
   // Server 端渲染和單元測試的時候可未必有 DOM 存在
   viewport: ExecutionEnvironment.canUseDOM ? 
    { width: window.innerWidth, height: window.innerHeight } : defaultViewport
  }
  componentDidMount() {
   // Server 端渲染是不會執行到 `componentDidMount` 的,只會執行到 `componentWillMount`
   window.addEventListener('resize', this.handleWindowResize)
   window.addEventListener('orientationchange', this.handleWindowResize)
  }
  componentWillUnmount() {
   window.removeEventListener('resize', this.handleWindowResize)
   window.removeEventListener('orientationchange', this.handleWindowResize)
  }
  render() {
   return <ComposedComponent {...this.props} viewport={this.state.viewport}/>
  }

  handleWindowResize() {
   const { viewport } = this.state
   if (viewport.width !== window.innerWidth || viewport.height !== window.innerHeight) {
    this.setState({ viewport: { width: window.innerWidth, height: window.innerHeight } })
   }  
  }
 }
}

*** 專業的實現參看 https://github.com/kriasoft/react-decorators ***

那么,下面我們就可以創建出一個有機會響應窗口大小變化的 Input 組件:

const SizeableInput = withViewport(Input)
ReactDOM.render(<SizeableInput name="username" label="Username" {...props} />, mountNode)

withViewort 作為一個 "高階組件" 可不僅僅是為了 Input 服務的。它可以為你需要的任何組件添加上 viewport 屬性,當窗口大小變化時,觸發重繪。

如果你用過 Redux,那么應該也熟悉 "connect decorator" 的用法。"connect decorator" 也是一個高階組件,因此,你可以繼續來“拼湊”:

const UserNameInput = connect(
 state => ({ value: state.username })
)(SizeableInput)

高階組件的存在有兩個好處:

  • 當寫著寫著無狀態組件的時候,有一天忽然發現需要狀態處理了,那么無需徹底返工:)

  • 往往我們需要狀態的時候,這個需求是可以重用的,例如上面的 withViewport,今后可以用來給其他組件(無論是否是無狀態組件)添加 viewport 屬性。

高階組件加無狀態組件,則大大增強了整個代碼的可測試性和可維護性。同時不斷“誘使”我們寫出組合性更好的代碼。

無狀態組件不支持 "ref"

有一點遺憾的是無狀態組件不支持 "ref"。原理很簡單,因為在 React 調用到無狀態組件的方法之前,是沒有一個實例化的過程的,因此也就沒有所謂的 "ref"。

ref 和 findDOMNode 這個組合,實際上是打破了父子組件之間僅僅通過 props 來傳遞狀態的約定,是危險且骯臟,需要避免。

無狀態組件尚不支持 babel-plugin-react-transform 的 Hot Module Replacement

如果你是用 Webpack 以及 HMR,用 babel-plugin-react-transform 來做 jsx 轉換等,那么當你在編輯器中修改無狀態組件的源代碼的時候,HMR 并不會在瀏覽器中自動載入修改后的代碼。具體問題跟蹤請參 https://github.com/gaearon/babel-plugin-react-transform/issues/57 。

以上是“React中無狀態組件與高階組件的示例分析”這篇文章的所有內容,感謝各位的閱讀!希望分享的內容對大家有幫助,更多相關知識,歡迎關注億速云行業資訊頻道!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

潞西市| 翁源县| 铜梁县| 台州市| 开化县| 阜南县| 莱芜市| 葫芦岛市| 贵港市| 昌宁县| 高台县| 邢台县| 琼结县| 大余县| 宁夏| 柏乡县| 保靖县| 黔西| 得荣县| 航空| 满洲里市| 绵阳市| 澄江县| 托克逊县| 无极县| 正蓝旗| 岳阳县| 万安县| 宣城市| 三明市| 邓州市| 文登市| 彰武县| 铜川市| 新津县| 安福县| 阿瓦提县| 来宾市| 普兰店市| 察隅县| 潜山县|