国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

如何寫好前端業務代碼?

kbyyd24 / 2767人閱讀

摘要:前言如何寫出可維護和可讀性高的代碼,這一直是一個困擾很多人的問題。總結在開始寫業務之前,理應先想清楚需求和業務邏輯,設計出合理的數據結構,對代碼進行好的分層,這樣在一定程度上可以寫出可維護性更高的代碼。

前言

如何寫出可維護和可讀性高的代碼,這一直是一個困擾很多人的問題。關于變量如何起名、如何優化if else之類的小技巧,這里就不做介紹了,推薦去看《代碼大全2》,千書萬書,都不如一本《代碼大全2》。

工作以來,我一直在寫一些重復且交互復雜的頁面,也沒有整理過自己的思路,這篇文章是我工作一年半來在項目中總結出來的一些經驗。

分層

對于業務代碼來說,大部分的前端應用都還是以展示數據為主,無非是從接口拿到數據,進行一系列數據格式化后,顯示在頁面當中。

首先,應當盡可能的進行分層,傳統的mvc分層很適用于前端開發,但對于復雜頁面來說,隨著業務邏輯增加,往往會造成controller臃腫的問題。因此,在此之上,可以將controller其分成formatter、service等等。


下面這是一些分層后簡單的目錄結構。

    + pages
        + hotelList
            + components
                + Header.jsx
            + formatter
                + index.js
            + share
                + constants.js
                + utils.js
            + view.js
            + controller.js
            + model.js
Service

統一管理所有請求路徑,并且將頁面中涉及到的網絡請求封裝為class。

// api.js
export default {
    HOTELLIST: "/hotelList",
    HOTELDETAIL: "/hotelDetail"
}

// Service.js
class Service {
    fetchHotelList = (params) => {
        return fetch(HOTELLIST, params);
    }
    fetchHotelDetail = (params) => {
        return fetch(HOTELLIST, params);
    }
}
export default new Service

這樣帶來的好處就是,很清楚的知道頁面中涉及了哪些請求,如果使用了TypeScript,后續某個請求方法名修改了后,在所有調用的地方也會提示錯誤,非常方便。

formatter

formatter層儲存一些格式化數據的方法,這些方法接收數據,返回新的數據,不應該再涉及到其他的邏輯,這樣有利于單元測試。單個format函數也不應該格式化過多數據,函數應該根據功能進行適當拆分,合理復用。

mvc

顧名思義,controller就是mvc中的c,controller應該是處理各種副作用操作(網絡請求、緩存、事件響應等等)的地方。

當處理一個請求的時候,controller會調用service里面對應的方法,拿到數據后再調用formatter的方法,將格式化后的數據存入store中,展示到頁面上。

class Controller {
    fetchHotelList = () => async (dispatch) => {
        const params = {}
        this.showLoading();
        try {
            const res = await Service.fetchHotelList(params)
            const hotelList = formatHotelList(res.Data && res.Data.HotelList)
            dispatch({
                type: "UPDATE_HOTELLIST",
                hotelList
            })
        } catch (err) {
            this.showError(err);
        } finally {
            this.hideLoading();
        }
    }
}

view則是指react組件,建議盡量用純函數組件,有了hooks之后,react也會變得更加純粹(實際上有狀態組件也可以看做一個mvc的結構,state是model,render是view,各種handler方法是controller)。

對于react來說,最外層的一般稱作容器組件,我們會在容器組件里面進行網絡請求等副作用的操作。

在這里,容器組件里面的一些邏輯也可以剝離出來放到controller中(react-imvc就是這種做法),這樣就可以給controller賦予生命周期,容器組件只用于純展示。

我們將容器組件的生命周期放到wrapper這個高階組件中,并在里面調用controller里面封裝的生命周期,這樣我們可以就編寫更加純粹的view,例如:

wrapper.js

// wrapper.js(偽代碼)
const Wrapper = (components) => {
    return class extends Component {
        constructor(props) {
            super(props)
        }
        componentWillMount() {
            this.props.pageWillMount && this.props.pageWillMount()
        }
        componentDidMount() {
                this.props.pageDidMount && this.props.pageDidMount()
            }
        }
        componentWillUnmount() {
            this.props.pageWillLeave && this.props.pageWillLeave()
        }
        render() {
            const {
                store: state,
                actions
            } = this.props
            return view({state, actions})
        }
    }
}

view.js

// view.js
function view({
    state,
    actions
}) {
    
    return (
        <>
            
) } export default Wrapper(view)

controller.js

// controller.js
class Controller {
    pageDidMount() {
        this.bindScrollEvent("on")
        console.log("page did  mount")
    }
    pageWillLeave() {
        this.bindScrollEvent("off")
        console.log("page will leave")
    }
    bindScrollEvent(status) {
        if (status === "on) {
            this.bindScrollEvent("off");
            window.addEventListener("scroll", this.handleScroll);
        } else if (status === "off") {
            window.removeEventListener("scroll", this.handleScroll);
        }
    }
    // 滾動事件
    handleScroll() {
        
    }
}
其他

對于埋點來說,原本也應該放到controller中,但也是可以獨立出來一個tracelog層,至于tracelog層如何實現和調用,還是看個人愛好,我比較喜歡用發布訂閱的形式。

如果還涉及到緩存,那我們也可以再分出來一個storage層,這里存放對緩存進行增刪查改的各種操作。

對于一些常用的固定不變的值,也可以放到constants.js,通過引入constants來獲取值,這樣便于后續維護。

// constants.js
export const cityMapping = {
    "1": "北京",
    "2": "上海"
}
export const traceKey = {
    "loading": "PAGE_LOADING"
}
// tracelog.js
class TraceLog {
    traceLoading = (params) => {
        tracelog(traceKey.loading, params);
    }
}
export default new TraceLog

// storage.js
export default class Storage {
    static get instance() {
        // 
    }
    setName(name) {
        //
    }
    getName() {
        //
    }
}
數據與交互

不過也不代表著這樣寫就夠了,分層只能夠保證代碼結構上的清晰,真正想寫出好的業務代碼,最重要的還是你對業務邏輯足夠清晰,頁面上的數據流動是怎樣的?數據結構怎么設計更加合理?頁面上有哪些交互?這些交互會帶來哪些影響?

以如下酒店列表頁為例,這個頁面看似簡單,實際上包含了很多復雜的交互。

上方的是四個篩選項菜單,點開后里面包含了很多子類篩選項,比如篩選里面包括了雙床、大床、三床,價格/星級里面包含了高檔/豪華、¥150-¥300等等。

下方是快捷篩選項,對應了部分篩選項菜單里面的子類篩選項。

當我們選中篩選里面的雙床后,下方的雙床也會被默認選中,反之當我們選中下方的雙床后,篩選類別里面的雙床也會被選中,名稱還會回顯到原來的篩選上。

除此之外,我們點擊搜索框后,輸入"雙床",聯想詞會出現雙床,并表示這是個篩選項,如果用戶選中了這個雙床,我們依然需要篩選項和快捷篩選項默認選中。

這三個地方都涉及到了篩選項,并且修改一個,其他兩個地方就要跟著改變,更何況三者的數據來自于三個不同的接口數據,這是多么蛋疼的一件事情!

我借助這個例子來說明,在開始寫頁面之前,一定要對頁面中的隱藏交互和數據流動很熟悉,也需要去設計更加合理的數據結構。

對于深層次的列表結構,鍵值對會比數組查詢速度更快,通過key也會更容易和其他數據進行聯動,但是卻不能保證順序,有時候可能就需要犧牲空間來換時間。

// 假設篩選項床型type為1,大床id為1,雙床id為2.
const bed = {
    "1-1": {
        name: "大床",
        id: 1,
        type: 1
    },
    "1-2": {
        name: "雙床",
        id: 2,
        type: 1
    }
}
const bedSort = ["1-1", "1-2"] // 保證展示順序

當我們選中大床的時候,只需要保存"1-1"這個key,再和store中快捷篩選項列表里面的key進行mapping(快捷篩選項里面的項也應該格式化為{"type-id": filterItem}的鍵值對格式),這樣從時間復雜度上說,比直接遍歷兩個數組更高效。

總結

在開始寫業務之前,理應先想清楚需求和業務邏輯,設計出合理的數據結構,對代碼進行好的分層,這樣在一定程度上可以寫出可維護性更高的代碼。

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/102792.html

相關文章

  • 我是如何對待寫靜態頁這項工作的

    摘要:開工,我是如何定義現代切圖的既然所有后臺都有計劃重做,那么統一風格那就是必須的了。我們前端部門采用的是自己搭建的。讓我使用,我是不樂意的。我采用提供一個服務,提供靜態頁面預覽。沒錯我就是這么直接。 歡迎一起交流 歡迎關注我的個人公眾號,不定期更新自己的工作心得。 showImg(https://segmentfault.com/img/bVEk23?w=258&h=258); 什么是靜...

    NickZhou 評論0 收藏0
  • 我是如何對待寫靜態頁這項工作的

    摘要:開工,我是如何定義現代切圖的既然所有后臺都有計劃重做,那么統一風格那就是必須的了。我們前端部門采用的是自己搭建的。讓我使用,我是不樂意的。我采用提供一個服務,提供靜態頁面預覽。沒錯我就是這么直接。 歡迎一起交流 歡迎關注我的個人公眾號,不定期更新自己的工作心得。 showImg(https://segmentfault.com/img/bVEk23?w=258&h=258); 什么是靜...

    hqman 評論0 收藏0
  • 后端開發者從零做一個移動應用(后端篇)

    摘要:后端開發的疑惑后端開發最常面對的一個問題性能高并發等等。而到了時代,在方面有了前后端分離概念移動后端更是無力渲染天然前后端分離。 先來上一張前端頁面的效果圖(Vue + Vux + Vuex + Vue-Router)。showImg(https://segmentfault.com/img/remote/1460000010207850); 第一次做gif 沒什么經驗,太大了。加載...

    codergarden 評論0 收藏0
  • 前端業務代碼配置化

    摘要:如何寫好業務代碼在前端工作中有很多業務性代碼,如果書寫不規范,那么對后期的維護將是非常致命的。代碼配置化在使用編寫代碼的過程中,經常用到這樣的情況,根據情況判斷是否展示對應的組件。 如何寫好業務代碼? 在前端工作中有很多業務性代碼,如果書寫不規范,那么對后期的維護將是非常致命的。 判斷配置化 業務場景 后端數據庫中經常會一個字段具備幾個不同的狀態,比如: status: 2 // 各...

    MSchumi 評論0 收藏0

發表評論

0條評論

kbyyd24

|高級講師

TA的文章

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