前端業務代碼配置化

如何寫好業務代碼?
在前端工作中有很多業務性代碼,如果書寫不規範,那麼對後期的維護將是非常致命的。

判斷配置化

業務場景

後端數據庫中經常會一個字段具備幾個不同的狀態,比如:

status: 2
// 各個字段對應的含義
0: 出生
1: 兒童
2: 少年
3: 中年
4: 老年
  • 這樣不同的數字代表的含義,需要在前端展示。
  • 需要根據不同的狀態,前端去做不同的處理

方法一(switch)(bad)

下面這段代碼就是常見的無限if/else或者switch場景

// 業務代碼
switch (status) {
    case 0: 
        // do something
        return '出生';
    case 1:
        // do something
        return '兒童';
    ... ...
    default:
        return '';
}

這樣做是不好的,因爲如果後端再加了一個字段,比如

5: 已死亡

那麼前端需要重新修改switch函數,這樣需要去修改對應的業務函數,無疑破壞了業務代碼的完整性。

方法二(寫成配置文件)(better)

// cfg.js
export const cfg = new Map([
    [0, 出生],
    [1, 兒童],
    [2, 少年],
    ... ... 
]);

// 業務代碼
cfg.get(status)

但是這樣僅僅是顯示相關的狀態,如果涉及到狀態的判斷,那這樣的處理方式就有些問題了,比如需要根據具體的狀態去做對應的判斷

switch (status) {
    case 0:
        // do something
        return ;
    ... ...

}

像上面的情況,又變成了第一種情況,顯然這種配置化的方式並不能滿足。如果將對應的操作,與配置分割,則代碼更加不易維護。

方法三(升級配置文件,處理代碼集中)(better)

將狀態處理集中起來,如果能將狀態展示和對應的狀態封裝起來,那麼就會讓後期代碼維護顯得十分集中。

// cfg.js
const status = new Map([
    [0, 出生],
    [1, 兒童],
    [2, 少年],
    ... ... 
]);
const checkIsBirth = (status, callback) => {
    if(status === 0) {
        callback && callback()
    }
}
export default {
    status,
    checkIsBirth
}
// 在具體使用中
import Person from './cfg.js'
const a = 1;
Person.status.get(a);
Person.checkIsBirth(a, () => {
    console.log('Person is in Birth state');
})

這樣處理,如果以後status發生變化,只需要修改checkIsBirth中的判斷邏輯就可以,只需要改動一處。

代碼配置化

在使用react編寫代碼的過程中,經常用到這樣的情況,根據情況判斷是否展示對應的組件。

方法一(流水線工作)(bad)

function Business({status, bug}) {
    return (
        <Fragment>
            {
                status === 0
                    ? (
                        <div>123</div>
                    )
                    : null
            }
            {
                bug === 1
                    ? (
                        <div>456</div>
                    )
                    : null
            }
        </Fragment>
    );
}

這樣的寫法如果僅僅只有一個其實還好,如果有很多個,在代碼中會造成代碼非常冗長,使假想一個頁面中如果有很多這樣的,代碼看起來非常ugly。所以建議將代碼分割開來,形成一個個小的組件,將對應的代碼封裝起來,將會使代碼可讀性提高一些。

方法二(組件粒度細化)(better)

function Business() {
    return (
        <Fragment>
            <One isShow={status === 0} />
            <One isShow={bug === 1} />
        </Fragment>
    );
}

// One
function One({isShow}) {
    return (
        <Fragment>
            {
                isShow === true
                ? (
                    <div>123</div>
                )
                : null
            }
        </Fragment>
    );
}

// Two
function Two({isShow}) {
    return (
        <Fragment>
            {
                isShow === true
                ? (
                    <div>456</div>
                )
                : null
            }
        </Fragment>
    );
}

如果經常這麼寫是不是會覺得很煩,可以將通用的邏輯抽象爲通用的組件。

方法三(高階組件)(better)

其實可以觀望一下decorator以後的用法,暫時沒有找到使用的切入點。

function IsShowCom(isShow, Wrapped) {
    if (isShow === true) {
        return (Wrapped) => <Wrapped />
    }
    return () => null;
}
// 如果你想轉發ref,你得這麼做
function IsShowCom(isShow, Wrapped) {
    if (isShow === true) {
        return React.forwardRef((props, ref) => {
            return <Wrapped {...props} ref={ref} /> 
        });
    }
    return () => null;
}
// 
import IsShowCom from './isShowCom';

function Business() {
    const One = IsShowCom(
        status === 0,
        <div>
            123
        </div>
    );
    const Two = IsShowCom(
        bug === 1,
        <div>
            456
        </div>
    );
    return (
        <Fragment>
            <One/>
            <Two/>
        </Fragment>
    );
}

注意⚠️

不要在render中使用高階組件,因爲高階組件每次返回來的都是新的組件,會使子組件的狀態丟失 。但是在無狀態組件中,這樣使用並沒有什麼問題,因爲無狀態組件本身就是隨參數的變化而變化的,只是可能會產生性能問題。

總結

前端配置化的整體思路:

  • 針對不同值進行不同處理的時候,思考一下,是不是可以將判斷邏輯代碼集中起來
  • 針對組件的顯示/隱藏,可以將具體的隱藏邏輯封裝爲高階組件,便於維護
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章