React.js 小書 Lesson4 - 前端組件化(三):抽象出公共組件類


React.js 小書 Lesson4 - 前端組件化(三):抽象出公共組件類

本文做者:鬍子大哈
本文原文:huziketang.com/books/react…javascript

轉載請註明出處,保留原文連接以及做者信息前端

在線閱讀:huziketang.com/books/reactjava


爲了讓代碼更靈活,能夠寫更多的組件,咱們把這種模式抽象出來,放到一個 Component 類當中:react

class Component {
    setState (state) {
      const oldEl = this.el
      this.state = state
      this.el = this._renderDOM()
      if (this.onStateChange) this.onStateChange(oldEl, this.el)
    }

    _renderDOM () {
      this.el = createDOMFromString(this.render())
      if (this.onClick) {
        this.el.addEventListener('click', this.onClick.bind(this), false)
      }
      return this.el
    }
  }複製代碼

這個是一個組件父類 Component,全部的組件均可以繼承這個父類來構建。它定義的兩個方法,一個是咱們已經很熟悉的 setState;一個是私有方法 _renderDOM_renderDOM 方法會調用 this.render 來構建 DOM 元素而且監聽 onClick 事件。因此,組件子類繼承的時候只須要實現一個返回 HTML 字符串的 render 方法就能夠了。git

還有一個額外的 mount 的方法,其實就是把組件的 DOM 元素插入頁面,而且在 setState 的時候更新頁面:github

const mount = (component, wrapper) => {
    wrapper.appendChild(component.renderDOM())
    component.onStateChange = (oldEl, newEl) => {
      wrapper.insertBefore(newEl, oldEl)
      wrapper.removeChild(oldEl)
    }
  }複製代碼

這樣的話咱們從新寫點贊組件就會變成:app

class LikeButton extends Component {
    constructor () {
      this.state = { isLiked: false }
    }

    onClick () {
      this.setState({
        isLiked: !this.state.isLiked
      })
    }

    render () {
      return ` <button class='like-btn'> <span class='like-text'>${this.state.isLiked ? '取消' : '點贊'}</span> <span>👍</span> </button> `
    }
  }

  mount(new LikeButton(), wrapper)複製代碼

這樣還不夠好。在實際開發當中,你可能須要給組件傳入一些自定義的配置數據。例如說想配置一下點贊按鈕的背景顏色,若是我給它傳入一個參數,告訴它怎麼設置本身的顏色。那麼這個按鈕的定製性就更強了。因此咱們能夠給組件類和它的子類都傳入一個參數 props,做爲組件的配置參數。修改 Component 的構造函數爲:less

...
    constructor (props = {}) {
      this.props = props
    }
...複製代碼

繼承的時候經過 super(props)props 傳給父類,這樣就能夠經過 this.props 獲取到配置參數:dom

class LikeButton extends Component {
    constructor (props) {
      super(props)
      this.state = { isLiked: false }
    }

    onClick () {
      this.setState({
        isLiked: !this.state.isLiked
      })
    }

    render () {
      return ` <button class='like-btn' style="background-color: ${this.props.bgColor}"> <span class='like-text'> ${this.state.isLiked ? '取消' : '點贊'} </span> <span>👍</span> </button> `
    }
  }

  mount(new LikeButton({ bgColor: 'red' }), wrapper)複製代碼

這裏咱們稍微修改了一下原有的 LikeButtonrender 方法,讓它能夠根據傳入的參數 this.props.bgColor 來生成不一樣的 style 屬性。這樣就能夠自由配置組件的顏色了。函數

只要有了上面那個 Component 類和 mount 方法加起來不足40行代碼就能夠作到組件化。若是咱們須要寫另一個組件,只須要像上面那樣,簡單地繼承一下 Component 類就行了:

class RedBlueButton extends Component {
    constructor (props) {
      super(props)
      this.state = {
        color: 'red'
      }
    }

    onClick () {
      this.setState({
        color: 'blue'
      })
    }

    render () {
      return ` <div style='color: ${this.state.color};'>${this.state.color}</div> `
    }
  }複製代碼

簡單好用,如今能夠靈活地組件化頁面了。

噢,忘了,還有一個神祕的 createDOMFromString,其實它更簡單:

const createDOMFromString = (domString) => {
    const div = document.createElement('div')
    div.innerHTML = domString
    return div
  }複製代碼

Component 完整的代碼能夠在這裏找到 reactjs-in-40

總結

咱們用了很長的篇幅來說一個簡單的點讚的例子,而且在這個過程裏面一直在優化編寫的方式。最後抽離出來了一個類,能夠幫助咱們更好的作組件化。在這個過程裏面咱們學到了什麼?

組件化能夠幫助咱們解決前端結構的複用性問題,整個頁面能夠由這樣的不一樣的組件組合、嵌套構成。

一個組件有本身的顯示形態(上面的 HTML 結構和內容)行爲,組件的顯示形態和行爲能夠由數據狀態(state)和配置參數(props)共同決定。數據狀態和配置參數的改變都會影響到這個組件的顯示形態。

當數據變化的時候,組件的顯示須要更新。因此若是組件化的模式能提供一種高效的方式自動化地幫助咱們更新頁面,那也就能夠大大地下降咱們代碼的複雜度,帶來更好的可維護性。

好了,課程結束了。你已經學會了怎麼使用 React.js 了,由於咱們已經寫了一個——固然我是在開玩笑,可是上面這個 Component 類其實和 React 的 Component 使用方式很相似。掌握了這幾節的課程,你基本就掌握了基礎的 React.js 的概念。

接下來咱們開始正式進入主題,開始正式介紹 React.js。你會發現,有了前面的鋪墊,下面講的內容理解起來會簡單不少了。

下一節連接直達:《React.js 小書 - Lesson5 React.js 基本環境安裝》

相關文章
相關標籤/搜索