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

資訊專欄INFORMATION COLUMN

react進階系列:高階組件詳解(二)

JouyPub / 1340人閱讀

摘要:高階組件可以封裝公共邏輯,給當前組件傳遞方法屬性,添加生命周期鉤子等。二是基礎(chǔ)組件的靜態(tài)方法也會因為高階組件的包裹會丟失。如果在開發(fā)中確實遇到了必須使用它們,就一定要注意高階組件的這個問題并認真解決。

高階組件可以封裝公共邏輯,給當前組件傳遞方法屬性,添加生命周期鉤子等。

案例:

一個項目中有的頁面需要判斷所處環(huán)境,如果在移動端則正常顯示頁面,并向用戶提示當前頁面所處的移動端環(huán)境,如果不在移動端則顯示提示讓其在移動端打開。但是有的頁面又不需要這個判斷。

如果在每個頁面都寫一段判斷邏輯未免麻煩,因此可以借助高階組件來處理這部分邏輯。

先創(chuàng)建一個高階組件

// src/container/withEnvironment/index.jsx
import React from "react";

const envs = {
    weixin: "微信",
    qq: "QQ",
    baiduboxapp: "手機百度",
    weibo: "微博",
    other: "移動端"
}

function withEnvironment(BasicComponent) {
    const ua = navigator.userAgent;
    const isMobile = "ontouchstart" in document;
    let env = "other";

    if (ua.match(/MicroMessenger/i)) {
        env = "weixin";
    }
    if (ua.match(/weibo/i)) {
        env = "weibo";
    }
    if (ua.match(/qq/i)) {
        env = "qq";
    }
    if (ua.match(/baiduboxapp/i)) {
        env = "baiduboxapp"
    }

    // 不同邏輯下返回不同的中間組件
    if (!isMobile) {
        return function () {
            return (
                
該頁面只能在移動端查看,請掃描下方二維碼打開。
假設(shè)這里有張二維碼
) } } // 通過定義的中間組件將頁面所處環(huán)境通過props傳遞給基礎(chǔ)組件 const C = props => ( ) return C; } export default withEnvironment;

然后在基礎(chǔ)組件中使用

// src/pages/Demo01/index.jsx
import React from "react";
import withEnvironment from "../../container/withEnvironment";

function Demo01(props) {
    return (
        
你現(xiàn)在正在{props.envdesc}中訪問該頁面
) } export default withEnvironment(Demo01);

最后將基礎(chǔ)組件渲染出來即可查看到效果。

// src/index.js
import React from "react";
import { render } from "react-dom";
import Demo01 from "./pages/Demo01";

const root = document.querySelector("#root");
render(, root);

在上面這個例子中,我們將環(huán)境判斷的邏輯放在了高階組件中處理,以后只要需要判斷環(huán)境的頁面只需要在基礎(chǔ)組件中這樣執(zhí)行即可。

export default withEnvironment(Demo01);

除此之外,我們在實際開發(fā)中還會遇到一個非常常見的需求,那就是在進入一個頁面時需要判斷登錄狀態(tài),登錄狀態(tài)與非登錄狀態(tài)的不同顯示,登錄狀態(tài)之后角色的不同顯示都可以通過高階組件統(tǒng)一來處理這個邏輯,然后將登錄狀態(tài),角色信息等傳遞給基礎(chǔ)組件。

// 大概的處理邏輯
import React from "react";
import $ from "jquery";

// 假設(shè)已經(jīng)封裝了一個叫做getCookie的方法獲取cookie
import { getCookie } from "cookie";

function withRule(BasicComponent) {

    return class C extends React.Component {
        state = {
            islogin: false,
            rule: -1,
            loading: true,
            error: null
        }

        componentDidMount() {
            // 如果能直接在cookie中找到uid,說明已經(jīng)登錄過并保存了相關(guān)信息
            if (getCookie("uid")) {
                this.setState({
                    islogin: true,
                    rule: getCookie("rule") || 0,
                    loading: false
                })
            } else {
                // 如果找不到uid,則嘗試自動登錄,先從kookie中查找是否保存了登錄賬號與密碼
                const userinfo = getCookie("userinfo");
                if (userinfo) {
                    // 調(diào)用登錄接口
                    $.post("/api/login", {
                        username: userinfo.username,
                        password: userinfo.password
                    }).then(resp => {
                        this.setState({
                            islogin: true,
                            rule: resp.rule,
                            islogin: false
                        })
                    }).catch(err => this.setState({ error: err.message }))
                } else {
                    // 當無法自動登錄時,你可以選擇在這里彈出登錄框,或者直接顯示未登錄頁面的樣式等都可以
                }
            }
        }

        render() {
            const { islogin, rule, loading, error } = this.state;

            if (error) {
                return (
                    
登錄接口請求失??!錯誤信息為:{error}
) } if (loading) { return (
頁面加載中, 請稍后...
) } return ( ) } } } export default withRule;

與第一個例子相比,這個例子更加接近實際應(yīng)用并且邏輯也更更加復雜。因此涉及到了異步數(shù)據(jù),因此最好的方式是在中間組件的componentDidMount中來處理邏輯。并在render中根據(jù)不同的狀態(tài)決定不同的渲染結(jié)果。

我們需要根據(jù)實際情況合理的使用react創(chuàng)建組件的兩種方式。這一點至關(guān)重要。上面兩個例子個人認為還是比較典型的能代表大多數(shù)情況。

react-router中的高階組件

我們在學習react的過程中,會逐漸的與高階組件打交道,react-router 中的 withRouter應(yīng)該算是會最早接觸到的高階組件。我們在使用的時候就知道,通過withRouter包裝的組件,我們可以在props中訪問到location, router等對象,這正是withRouter通過高階組件的方式傳遞過來的。

import React, { Component } from "react";
import { withRouter } from "react-router";

class Home extends Component {
    componentDidMount() {
        const { router } = this.props;

        router.push("/");
    }
    render() {
        return (
            
...
) } } export default withRouter(Home);

我們可以來看看在react-router v4withRouter的源碼。

import React from "react";
import PropTypes from "prop-types";
import hoistStatics from "hoist-non-react-statics";
import Route from "./Route";

// 傳入基礎(chǔ)組件作為參數(shù)
const withRouter = (Component) => {

    // 創(chuàng)建中間組件
    const C = (props) => {
        const { wrappedComponentRef, ...remainingProps } = props;
        return (
             (
                // wrappedComponentRef 用來解決高階組件無法正確獲取到ref的問題
                
            )}/>
        )
    }

    C.displayName = `withRouter(${Component.displayName || Component.name})`;
    C.WrappedComponent = Component;
    C.propTypes = {
        wrappedComponentRef: PropTypes.func
    }

    // hoistStatics類似于Object.assign,用于解決基礎(chǔ)組件因為高階組件的包裹而丟失靜態(tài)方法的問題
    return hoistStatics(C, Component);
}

export default withRouter;

如果對于高階組件的例子你已經(jīng)熟知,那么withRouter的源碼其實很容易理解。它做所的工作就僅僅只是把routeComponentProps傳入基礎(chǔ)組件而已。

另外還需要注意點是在該源碼中,解決了兩個因為高階組件帶來的問題,一個是經(jīng)過高階組件包裹的組件在使用時無法通過ref正確獲取到對應(yīng)的值。二是基礎(chǔ)組件的靜態(tài)方法也會因為高階組件的包裹會丟失。不過好在這段源碼已經(jīng)給我們提供了對應(yīng)的解決方案。因此如果我們在使用中需要處理這2點的話,按照這里的方式來做就可以了。

但是通常情況下,我們也很少會在自定義的組件中添加靜態(tài)方法和使用ref。如果在開發(fā)中確實遇到了必須使用它們,就一定要注意高階組件的這2個問題并認真解決。

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

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

相關(guān)文章

  • react進階系列 - 高階組件詳解四:高階組件的嵌套使用

    摘要:前面有講到過很多頁面會在初始時驗證登錄狀態(tài)與用戶角色。這個時候就涉及到一個高階組件的嵌套使用。而每一個高階組件函數(shù)執(zhí)行之后中所返回的組件,剛好可以作為下一個高階組件的參數(shù)繼續(xù)執(zhí)行,而并不會影響基礎(chǔ)組件中所獲得的新能力。 前面有講到過很多頁面會在初始時驗證登錄狀態(tài)與用戶角色。我們可以使用高階組件來封裝這部分驗證邏輯。封裝好之后我們在使用的時候就可以如下: export default w...

    LMou 評論0 收藏0
  • react進階系列高階組件詳解(三)

    摘要:在前端基礎(chǔ)進階八深入詳解函數(shù)的柯里化一文中,我有分享柯里化相關(guān)的知識。雖然說高階組件與柯里化都屬于比較難以理解的知識點,但是他們組合在一起使用時并沒有新增更多的難點。 可能看過我以前文章的同學應(yīng)該會猜得到當我用New的方法來舉例學習高階組件時,接下來要分享的就是柯里化了。高階組件與函數(shù)柯里化的運用是非常能夠提高代碼逼格的技巧,如果你有剩余的精力,完全可以花點時間學習一下。 在前端基礎(chǔ)進...

    zhangxiangliang 評論0 收藏0
  • react進階系列高階組件詳解(一)

    摘要:創(chuàng)建一個普通函數(shù)因為的存在所以變成構(gòu)造函數(shù)創(chuàng)建一個方法在方法中,創(chuàng)建一個中間實例對中間實例經(jīng)過邏輯處理之后返回使用方法創(chuàng)建實例而恰好,高階組件的創(chuàng)建邏輯與使用,與這里的方法完全一致。因為方法其實就是構(gòu)造函數(shù)的高階組件。 很多人寫文章喜歡把問題復雜化,因此當我學習高階組件的時候,查閱到的很多文章都給人一種高階組件高深莫測的感覺。但是事實上卻未必。 有一個詞叫做封裝。相信寫代碼這么久了,大...

    NervosNetwork 評論0 收藏0
  • 前端文檔收集

    摘要:系列種優(yōu)化頁面加載速度的方法隨筆分類中個最重要的技術(shù)點常用整理網(wǎng)頁性能管理詳解離線緩存簡介系列編寫高性能有趣的原生數(shù)組函數(shù)數(shù)據(jù)訪問性能優(yōu)化方案實現(xiàn)的大排序算法一怪對象常用方法函數(shù)收集數(shù)組的操作面向?qū)ο蠛驮屠^承中關(guān)鍵詞的優(yōu)雅解釋淺談系列 H5系列 10種優(yōu)化頁面加載速度的方法 隨筆分類 - HTML5 HTML5中40個最重要的技術(shù)點 常用meta整理 網(wǎng)頁性能管理詳解 HTML5 ...

    jsbintask 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<