1. 程式人生 > >react學習--高階元件

react學習--高階元件

原來react使用混入(mixins)技術來解決交叉問題,但是react意識到混入(mixins)技術產生的問題要比帶來的價值大(react學習--react為何移除mixins 這篇博文可以看下),所以也就有了高階元件來解決交叉問題。

高階元件(HOC)是react中對元件邏輯進行重用的高階技術。但高階元件本身並不是React API。它只是一種模式,這種模式是由react自身的組合性質必然產生的。具體而言,高階元件就是一個函式,且該函式接受一個元件作為引數,並返回一個新的元件。新元件承受業務邏輯,並將資料傳入給接收的元件,接收的元件變成UI元件,只負責使用資料,而生成的新元件稱為容器元件。

下面通過一個小demo來看一下高階組建的應用。

資料和一些方法:

//資料和一些方法
const Datasource = {
    data: { // 存放資料
        comments: [
            {id: 1, title: '今天是個好日子'},
            {id: 2, title: '心想的事兒都能成'}
        ],
        blogPost: [
            {id: 1, title: '床前明月光'},
            {id: 2, title: '疑是地上霜'},
        ]
    },
    getComments () {
        return this.data.comments
    },
    getBlogPost () {
        return this.data.blogPost
    },
    handlers: [],
    addChangeListener (handler) {
        this.handlers.push(handler)
    },
    removeChangeListener (handler) {
        this.handlers = this.handlers.filter(item => item !== handler)
    },
    changeComments () {
        this.data.comments.push({ id: 3, title: '今個老百姓真開心' })
        this.emit()
    },
    changeBlogPost () {
        this.data.blogPost.push({ id: 3, title: '舉頭望明月' })
        this.emit()
    },
    emit () {
        this.handlers.forEach(handler => handler())
    }

}


UI元件1(木偶元件)

//UI元件 木偶元件
class CommentList extends Component {
    render () {
        return (
            <div>
                <h2>CommentList</h2>
                <ul className = "list-group">
                    {
                        this.props.lists.map(item => <li key = {item.id} 
className="list-group-item">{item.title}</li>)
                    }
                </ul>
            </div>
        )
    }
}
// 負責資料的邏輯處理,將其傳遞給UI元件, 此為容器元件 智慧元件
const Container = higherOrderComponent(CommentList, () => Datasource.getComments())

export default Container

UI元件2(木偶元件)

class BlogList extends Component {
    
    render () {
        return (
            <div>
                <h3>BlogtList</h3>
                <ol className = "list-group">
                    {
                        this.props.lists.map(item => <li key = {item.id} 
className="list-group-item">{item.title}</li>)
                    }
                </ol>
            </div>
        )
    }
}


export default higherOrderComponent(BlogList, () =>  Datasource.getBlogPost() )

高階元件:

const higherOrderComponent = (UIComponent, handler) => {
    return class extends Component {
        constructor () {
            super()
            this.state = {
                lists: handler()
            }
            this.handleChange = this.handleChange.bind(this)
           
        }
        componentDidMount () {
            Datasource.addChangeListener(this.handleChange)
        }
        componentWillUnmount () {
            Datasource.removeChangeListener(this.handleChange)
        }
        handleChange () {
            this.setState({lists: handler()})
        }
        render () {
            return <UIComponent {...this.state}/>
        }
    }
}

export default higherOrderComponent

父元件:

class HocExample extends Component {
    render () {
        return (
            <div>
                <button onClick = { Datasource.changeComments }>change comments</button>
                <CommentList/>  
                <BlogPost/>
            </div>
        )
    }
}

簡要講解:

  • 掛載元件時, 向 DataSource 新增一個監聽函式。
  • 在監聽函式內, 每當資料來源發生變化,都是呼叫 setState函式設定新資料。
  • 解除安裝元件時, 移除監聽函式。