最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

React Native項目框架搭建的一些心得體會

 更新時間:2021年05月28日 09:34:58   投稿:mrr  
React Native使你能夠在Javascript和React的基礎上獲得完全一致的開發(fā)體驗,構建世界一流的原生APP。接下來通過本文給大家分享React Native項目框架搭建的一些心得體會,感興趣的朋友跟隨小編一起看看吧

React Native 是Facebook于2015年4月開源的跨平臺移動應用開發(fā)框架, 短短的一兩年的發(fā)展就已經有很多家公司支持并采用此框架來搭建公司的移動端的應用,
React Native使你能夠在Javascript和React的基礎上獲得完全一致的開發(fā)體驗,構建世界一流的原生APP。

項目框架與項目結構

1. 項目中使用的技術棧

react native、react hook、typescript、immer、tslint、jest等.

都是比較常見的,就不多做介紹了

2. 數(shù)據(jù)處理使用的是react hook中的useContext+useReducer

思想與redux是一致的,用起來相對比較簡單,適合不太復雜的業(yè)務場景.

const HomeContext = createContext<IContext>({
  state: defaultState,
  dispatch: () => {}
});
const ContextProvider = ({ urlQuery, pageCode }: IProps) => {
  const initState = getInitState(urlQuery, pageCode);
  const [state, dispatch]: [IHomeState, IDispatch] = useReducer(homeReducer, initState);

  return (
    <HomeContext.Provider value={{ state, dispatch }}>
      <HomeContainer />
    </HomeContext.Provider>
  );
};
const HomeContainer = () => {
const { dispatch, state } = useContext(HomeContext);
...

3. 項目的結構如下

|-page1
    |-handler   // 處理邏輯的純函數(shù),需進行UT覆蓋
    |-container // 整合數(shù)據(jù)、行為與組件
    |-component // 純UI組件,展示內容與用戶交互,不處理業(yè)務邏輯
    |-store     // 數(shù)據(jù)結構不能超過3層,可使用外部引用、冗余字段的方式降低層級
    |-reducer   // 使用immer返回新的數(shù)據(jù)(immutable data)
    |-...
|-page2
|-...

項目中的規(guī)范

1. Page

整個項目做為一個多頁應用,最基本的拆分單元是page.

每一個page有相應的store,并非整個項目使用一個store,這樣做的原因如下:

  • 各個頁面的邏輯相對獨立
  • 各個頁面都可作為項目入口
  • 結合RN頁面生命周期進行數(shù)據(jù)處理(避免數(shù)據(jù)初始化、緩存等一系列問題)

各個頁面中與外部相關的操作,都在Page組件中定義

  • 頁面跳轉邏輯
  • 回退之后要處理的事件
  • 需要操作哪些storage中的數(shù)據(jù)
  • 需要請求哪些服務等等

Page組件的主要作用

以其自身業(yè)務模塊為基礎,把可以抽象出來的外部依賴、外部交互都集中到此組件的代碼中.

方便開發(fā)人員在進行各個頁面間邏輯編寫、問題排查時,可根據(jù)具體頁面+數(shù)據(jù)源,準確定位到具體的代碼.

2. reducer

在以往的項目中,reducer中可能會涉及部分數(shù)據(jù)處理、用戶行為、日志埋點、頁面跳轉等等代碼邏輯.

因為在開發(fā)人員寫代碼的過程中,發(fā)現(xiàn)reducer作為某個處理邏輯的終點(更新了state之后,此次事件即為結束),很適合去做這些事情.

隨著項目的維護,需求的迭代,reducer的體積不斷的增大.

因為缺乏條理,代碼量又龐大,再想去對代碼進行調整,只會困難重重.

讓你去維護這樣的一個項目,可想而知,將會是多么的痛苦.

為此,對reducer中的代碼進行了一些減法:

  • reducer中只對state的數(shù)據(jù)進行修改
  • 使用immer的produce產生immutable data
  • 冗余單獨字段的修改,進行整合,枚舉出頁面行為對應的action

reducer的主要作用

以可枚舉的形式,匯總出頁面中所有操作數(shù)據(jù)的場景.

在其本身適用于react框架的特性之外,賦予一定的業(yè)務邏輯閱讀屬性,在不依賴UI組件的情況下,可大致閱讀出頁面中的所有數(shù)據(jù)處理邏輯.

// 避免dispatch時進行兩次,且定義過多單字段的更新case
// 整合此邏輯后,與頁面上的行為相關聯(lián),利于理解、閱讀
case EFHListAction.updateSpecifyQueryMessage:
    return produce(state, (draft: IFHListState) => {
        draft.specifyQueryMessage = payload as string;
        draft.showSpecifyQueryMessage = true;
    });    
case EFHListAction.updateShowSpecifyQueryMessage:
    return produce(state, (draft: IFHListState) => {
        draft.showSpecifyQueryMessage = payload as boolean;
    });

3. handler

這里先引入一個純函數(shù)的概念:

一個函數(shù)的返回結果只依賴于它的參數(shù),并且在執(zhí)行過程里面沒有副作用,我們就把這個函數(shù)叫做純函數(shù).

把盡可能多的邏輯抽象為純函數(shù),然后放入handler中:

  • 涵蓋較多的業(yè)務邏輯
  • 只能是純函數(shù)
  • 必須進行UT覆蓋

handler的主要作用

負責數(shù)據(jù)源到store、container到component、dispatch到reducer等等場景下的邏輯處理.

作為各類場景下,邏輯處理函數(shù)的存放地,整個文件不涉及頁面流程上的關聯(lián)關系,每個函數(shù)只要滿足其輸入與輸出的使用場景,即可復用,多用于container文件中.

export function getFilterAndSortResult(
  flightList: IFlightInfo[],
  filterList: IFilterItem[],
  filterShare: boolean,
  filterOnlyDirect: boolean,
  sortType: EFlightSortType
) {
  if (!isValidArray(flightList)) {
    return [];
  }

  const sortFn = getSortFn(sortType);
  const result = flightList.filter(v => doFilter(v, filterList, filterShare, 1, filterOnlyDirect)).sort(sortFn);

  return result;
}
describe(getFilterAndSortResult.name, () => {
  test('getFilterAndSortResult', () => {
    expect(getFilterAndSortResult(flightList, filterList, false, EFlightSortType.PriceAsc)).toEqual(filterSortResult);
  });
});

4. Container

由上面的項目結構圖可以看出,每個Page都有base Container,作為數(shù)據(jù)處理的中心.

在此base Container之下,會根據(jù)不同模塊,定義出各個子Container:

  • 生命周期處理(初始化時要進行的一些異步操作)
  • 為渲染組件Components提供數(shù)據(jù)源
  • 定義頁面中的行為函數(shù)

Container的主要作用

整個項目中,各種數(shù)據(jù)、UI、用戶行為的匯合點,要盡可能的把相關的模塊抽離出來,避免造成代碼量過大,難以維護的情況.

Container的定義應以頁面展示的模塊進行抽象.如Head Contianer、Content Container、Footer Container等較為常見的劃分方式.

一些頁面中相對獨立的模塊,也應該產出其對應的Container,來內聚相關邏輯,如贈送優(yōu)惠券模塊、用戶反饋模塊等.

特別注意的是行為函數(shù)

  • 多個Container中公用的行為,可直接放入base Container中
  • 在上文架構圖中的action事例(setAction)為另外一種行為復用,根據(jù)具體的場景進行應用

利于代碼閱讀,A模塊的浮層展示邏輯,B模塊使用時
模塊產生的先后順序,先有A模塊再有B模塊需要使用A的方法

  • 定義數(shù)據(jù)埋點、用戶行為埋點
  • 頁面跳轉方法的調用(Page-->base Container-->子Container)
  • 其他副作用的行為
const OWFlightListContainer = () => {
    // 通過Context獲取數(shù)據(jù)
    const { state, dispatch } = useContext(OWFlightListContext);
    ...

    // 初次加載時進行超時的倒計時
    useOnce(overTimeCountDown);
    ...
    
    // 用戶點擊排序
    const onPressSort = (lastSortType: EFlightSortType, isTimeSort: boolean) => {
        // 引用了handler中的getNextSortType函數(shù)
        const sortType = getNextSortType(lastSortType, isTimeSort);
        dispatch({ type: EOWFlightListAction.updateSortType, payload: sortType });
        
        // 埋點操作
        logSort(state, sortType);
    };
    
    // 渲染展示組件
    return <.../>;
}

小結

由easy to code到easy to read
在整個項目中,定義了很多規(guī)范,是想在功能的實現(xiàn)之上,更利于項目人員的維護.

  • Page組件中包含頁面相關的外部依賴
  • reducer枚舉出所有對頁面數(shù)據(jù)操作的事件
  • handler中集合了業(yè)務邏輯的處理,以純函數(shù)的實現(xiàn)及UT的覆蓋,確保項目質量
  • Container中的行為函數(shù),定義出所有與用戶操作相關的事件,并記錄埋點數(shù)據(jù)
  • Componet中避免出現(xiàn)業(yè)務邏輯的處理,只進行UI展示,減少UI自動化case,增加UT的case

規(guī)范的定義是比較容易的,想要維護好一個項目,更多的是依靠團隊的成員,在達成共識的前提下,持之以恒的堅持了

分享幾個實用的函數(shù)

根據(jù)對象路徑取值

/**
 * 根據(jù)對象路徑取值
 * @param target {a: { b: { c: [1] } } }
 * @param path 'a.b.c.0'
 */
export function getVal(target: any, path: string, defaultValue: any = undefined) {
  let ret = target;
  let key: string | undefined = '';
  const pathList = path.split('.');

  do {
    key = pathList.shift();
    if (ret && key !== undefined && typeof ret === 'object' && key in ret) {
      ret = ret[key];
    } else {
      ret = undefined;
    }
  } while (pathList.length && ret !== undefined);

  return ret === undefined || ret === null ? defaultValue : ret;
}

// DEMO
const errorCode = getVal(result, 'rstlist.0.type', 0);

讀取根據(jù)配置信息

// 在與外部對接時,經常會定義一些固定結構,可擴展性的數(shù)據(jù)列表
// 為了適應此類契約,便于更好的閱讀與維護,總結出了以下函數(shù)
export const GLOBAL_NOTE_CONFIG = {
  2: 'refund',
  3: 'sortType',
  4: 'featureSwitch'
};

/**
 * 根據(jù)配置,獲取attrList中的值,返回json對象類型的數(shù)據(jù)
 * @private
 * @memberof DetailService
 */
export function getNoteValue<T>(
  noteList: Array<T> | undefined | null,
  config: { [_: string]: string },
  keyName: string = 'type'
) {
  const ret: { [_: string]: T | Array<T> } = {};

  if (!isValidArray(noteList!)) {
    return ret;
  }

  //@ts-ignore
  noteList.forEach((note: any) => {
    const typeStr: string = (('' + note[keyName]) as unknown) as string;

    if (!(typeStr in config)) {
      return;
    }

    if (note === undefined || note === null) {
      return;
    }

    const key = config[typeStr];

    // 有多個值時,改為數(shù)組類型
    if (ret[key] === undefined) {
      ret[key] = note;
    } else if (Array.isArray(ret[key])) {
      (ret[key] as T[]).push(note);
    } else {
      const first = ret[key];
      ret[key] = [first, note];
    }
  });

  return ret;
}

// DEMO
// 適用于外部定義的一些可擴展note節(jié)點列表的取值邏輯
const { sortType, featureSwitch } = getNoteValue(list, GLOBAL_NOTE_CONFIG, 'ntype');


 

多條件數(shù)組排序

/**
 * 獲取用于排序的sort函數(shù)
 * @param fn 同類型元素比較函數(shù),true為排序優(yōu)先
 */
export function getSort<T>(fn: (a: T, b: T) => boolean): (a: T, b: T) => 1 | -1 | 0 {
  return (a: T, b: T): 1 | -1 | 0 => {
    let ret = 0;

    if (fn.call(null, a, b)) {
      ret = -1;
    } else if (fn.call(null, b, a)) {
      ret = 1;
    }

    return ret as 0;
  };
}

/**
 * 多重排序
 */
export function getMultipleSort<T>(arr: Array<(a: T, b: T) => 1 | -1 | 0>) {
  return (a: T, b: T) => {
    let tmp;
    let i = 0;

    do {
      tmp = arr[i++](a, b);
    } while (tmp === 0 && i < arr.length);

    return tmp;
  };
}

// DEMO
const ageSort = getSort(function(a, b) {
  return a.age < b.age;
});

const nameSort = getSort(function(a, b) {
  return a.name < b.name;
});

const sexSort = getSort(function(a, b) {
  return a.sex && !b.sex;
});

//判斷條件先后順序可調整
const arr = [nameSort, ageSort, sexSort];

const ret = data.sort(getMultipleSort(arr));

以上就是React Native項目框架搭建的一些心得體會的詳細內容,更多關于React Native項目框架搭建的資料請關注腳本之家其它相關文章!

相關文章

  • react?定位組件源碼解析

    react?定位組件源碼解析

    這篇文章主要為大家介紹了react定位組件源碼解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-03-03
  • React 中合成事件的實現(xiàn)示例

    React 中合成事件的實現(xiàn)示例

    本文主要介紹了React 中合成事件的實現(xiàn)示例,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2025-02-02
  • React封裝高階組件實現(xiàn)路由權限的控制詳解

    React封裝高階組件實現(xiàn)路由權限的控制詳解

    這篇文章主要介紹了React封裝高階組件實現(xiàn)路由權限的控制,在React中,為了實現(xiàn)安全可靠的路由權限控制,可以通過多種方式來確保只有經過授權的用戶才能訪問特定路徑下的資源,下面來介紹封裝高階組件控制的方法,需要的朋友可以參考下
    2025-02-02
  • react封裝Dialog彈框的方法

    react封裝Dialog彈框的方法

    這篇文章主要為大家詳細介紹了react封裝Dialog彈框的方法,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-08-08
  • React實現(xiàn)全局組件的Toast輕提示效果

    React實現(xiàn)全局組件的Toast輕提示效果

    這篇文章主要介紹了React實現(xiàn)全局組件的Toast輕提示效果,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-09-09
  • vite?+?react?+typescript?環(huán)境搭建小白入門教程

    vite?+?react?+typescript?環(huán)境搭建小白入門教程

    這篇文章主要介紹了vite?+?react?+typescript?環(huán)境搭建小白入門教程,本文通過示例圖文相結合給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2022-12-12
  • create-react-app使用antd按需加載的樣式無效問題的解決

    create-react-app使用antd按需加載的樣式無效問題的解決

    這篇文章主要介紹了create-react-app使用antd按需加載的樣式無效問題的解決,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2019-02-02
  • React 小技巧教你如何擺脫hooks依賴煩惱

    React 小技巧教你如何擺脫hooks依賴煩惱

    Hooks 是一種函數(shù),該函數(shù)允許您從函數(shù)式組件 “勾住(hook into)” React 狀態(tài)和生命周期功能。 Hooks 在類內部不起作用 - 它們允許你無需類就使用 React,本文帶領大家學習React 小技巧教你如何擺脫hooks依賴煩惱,感興趣的朋友一起看看吧
    2021-05-05
  • react中的雙向綁定你真的了解嗎

    react中的雙向綁定你真的了解嗎

    這篇文章主要為大家詳細介紹了react中的雙向綁定,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助
    2022-03-03
  • npx create-react-app xxx創(chuàng)建項目報錯的解決辦法

    npx create-react-app xxx創(chuàng)建項目報錯的解決辦法

    這篇文章主要介紹了npx create-react-app xxx創(chuàng)建項目報錯的解決辦法,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2020-02-02

最新評論

淮南市| 祁连县| 金阳县| 颍上县| 兴仁县| 桂林市| 舒城县| 沈丘县| 鸡泽县| 涿州市| 麻阳| 盐亭县| 大足县| 佛坪县| 大新县| 潮安县| 沙洋县| 湖州市| 锡林郭勒盟| 盘锦市| 子长县| 会昌县| 瑞安市| 图片| 南充市| 寿阳县| 安化县| 灵寿县| 禹城市| 河东区| 安吉县| 郁南县| 拉萨市| 南通市| 仪陇县| 富川| 南京市| 林州市| 大方县| 图木舒克市| 武平县|