欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

React Native項(xiàng)目框架搭建的一些心得體會(huì)

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

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

項(xiàng)目框架與項(xiàng)目結(jié)構(gòu)

1. 項(xiàng)目中使用的技術(shù)棧

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

都是比較常見(jiàn)的,就不多做介紹了

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

思想與redux是一致的,用起來(lái)相對(duì)比較簡(jiǎn)單,適合不太復(fù)雜的業(yè)務(wù)場(chǎng)景.

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. 項(xiàng)目的結(jié)構(gòu)如下

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

項(xiàng)目中的規(guī)范

1. Page

整個(gè)項(xiàng)目做為一個(gè)多頁(yè)應(yīng)用,最基本的拆分單元是page.

每一個(gè)page有相應(yīng)的store,并非整個(gè)項(xiàng)目使用一個(gè)store,這樣做的原因如下:

  • 各個(gè)頁(yè)面的邏輯相對(duì)獨(dú)立
  • 各個(gè)頁(yè)面都可作為項(xiàng)目入口
  • 結(jié)合RN頁(yè)面生命周期進(jìn)行數(shù)據(jù)處理(避免數(shù)據(jù)初始化、緩存等一系列問(wèn)題)

各個(gè)頁(yè)面中與外部相關(guān)的操作,都在Page組件中定義

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

Page組件的主要作用

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

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

2. reducer

在以往的項(xiàng)目中,reducer中可能會(huì)涉及部分?jǐn)?shù)據(jù)處理、用戶行為、日志埋點(diǎn)、頁(yè)面跳轉(zhuǎn)等等代碼邏輯.

因?yàn)樵陂_發(fā)人員寫代碼的過(guò)程中,發(fā)現(xiàn)reducer作為某個(gè)處理邏輯的終點(diǎn)(更新了state之后,此次事件即為結(jié)束),很適合去做這些事情.

隨著項(xiàng)目的維護(hù),需求的迭代,reducer的體積不斷的增大.

因?yàn)槿狈l理,代碼量又龐大,再想去對(duì)代碼進(jìn)行調(diào)整,只會(huì)困難重重.

讓你去維護(hù)這樣的一個(gè)項(xiàng)目,可想而知,將會(huì)是多么的痛苦.

為此,對(duì)reducer中的代碼進(jìn)行了一些減法:

  • reducer中只對(duì)state的數(shù)據(jù)進(jìn)行修改
  • 使用immer的produce產(chǎn)生immutable data
  • 冗余單獨(dú)字段的修改,進(jìn)行整合,枚舉出頁(yè)面行為對(duì)應(yīng)的action

reducer的主要作用

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

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

// 避免dispatch時(shí)進(jìn)行兩次,且定義過(guò)多單字段的更新case
// 整合此邏輯后,與頁(yè)面上的行為相關(guān)聯(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

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

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

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

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

handler的主要作用

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

作為各類場(chǎng)景下,邏輯處理函數(shù)的存放地,整個(gè)文件不涉及頁(yè)面流程上的關(guān)聯(lián)關(guān)系,每個(gè)函數(shù)只要滿足其輸入與輸出的使用場(chǎng)景,即可復(fù)用,多用于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

由上面的項(xiàng)目結(jié)構(gòu)圖可以看出,每個(gè)Page都有base Container,作為數(shù)據(jù)處理的中心.

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

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

Container的主要作用

整個(gè)項(xiàng)目中,各種數(shù)據(jù)、UI、用戶行為的匯合點(diǎn),要盡可能的把相關(guān)的模塊抽離出來(lái),避免造成代碼量過(guò)大,難以維護(hù)的情況.

Container的定義應(yīng)以頁(yè)面展示的模塊進(jìn)行抽象.如Head Contianer、Content Container、Footer Container等較為常見(jiàn)的劃分方式.

一些頁(yè)面中相對(duì)獨(dú)立的模塊,也應(yīng)該產(chǎn)出其對(duì)應(yīng)的Container,來(lái)內(nèi)聚相關(guān)邏輯,如贈(zèng)送優(yōu)惠券模塊、用戶反饋模塊等.

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

  • 多個(gè)Container中公用的行為,可直接放入base Container中
  • 在上文架構(gòu)圖中的action事例(setAction)為另外一種行為復(fù)用,根據(jù)具體的場(chǎng)景進(jìn)行應(yīng)用

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

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

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

小結(jié)

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

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

規(guī)范的定義是比較容易的,想要維護(hù)好一個(gè)項(xiàng)目,更多的是依靠團(tuán)隊(duì)的成員,在達(dá)成共識(shí)的前提下,持之以恒的堅(jiān)持了

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

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

/**
 * 根據(jù)對(duì)象路徑取值
 * @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ù)配置信息

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

/**
 * 根據(jù)配置,獲取attrList中的值,返回json對(duì)象類型的數(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];

    // 有多個(gè)值時(shí),改為數(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
// 適用于外部定義的一些可擴(kuò)展note節(jié)點(diǎn)列表的取值邏輯
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;
});

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

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

以上就是React Native項(xiàng)目框架搭建的一些心得體會(huì)的詳細(xì)內(nèi)容,更多關(guān)于React Native項(xiàng)目框架搭建的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • 詳解React開發(fā)中使用require.ensure()按需加載ES6組件

    詳解React開發(fā)中使用require.ensure()按需加載ES6組件

    本篇文章主要介紹了詳解React開發(fā)中使用require.ensure()按需加載ES6組件,非常具有實(shí)用價(jià)值,需要的朋友可以參考下
    2017-05-05
  • react-native fetch的具體使用方法

    react-native fetch的具體使用方法

    本篇文章主要介紹了react-native fetch的具體使用方法,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2017-11-11
  • React項(xiàng)目配置prettier和eslint的方法

    React項(xiàng)目配置prettier和eslint的方法

    這篇文章主要介紹了React項(xiàng)目配置prettier和eslint的相關(guān)知識(shí),本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-06-06
  • React?Hook?Form?優(yōu)雅處理表單使用指南

    React?Hook?Form?優(yōu)雅處理表單使用指南

    這篇文章主要為大家介紹了React?Hook?Form?優(yōu)雅處理表單使用指南,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-03-03
  • 如何利用React實(shí)現(xiàn)圖片識(shí)別App

    如何利用React實(shí)現(xiàn)圖片識(shí)別App

    圖片識(shí)別這個(gè)功能在很多app中都有,下面這篇文章主要給大家介紹了關(guān)于如何利用React實(shí)現(xiàn)圖片識(shí)別App的相關(guān)資料,文中通過(guò)實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2022-01-01
  • hooks中useEffect()使用案例詳解

    hooks中useEffect()使用案例詳解

    這篇文章主要介紹了hooks中useEffect()使用總結(jié),本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-09-09
  • React學(xué)習(xí)筆記之列表渲染示例詳解

    React學(xué)習(xí)筆記之列表渲染示例詳解

    最近在學(xué)習(xí)React,學(xué)習(xí)到了列表渲染這一塊,發(fā)現(xiàn)網(wǎng)上這方面的資料較少,所以自己來(lái)總結(jié)下,下面這篇文章主要給大家介紹了關(guān)于React學(xué)習(xí)筆記之列表渲染的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),需要的朋友可以參考借鑒,下面來(lái)一起看看吧。
    2017-08-08
  • React技巧之中斷map循環(huán)的方法詳解

    React技巧之中斷map循環(huán)的方法詳解

    這篇文章主要和大家來(lái)分享一下React的技巧之如何中斷map循環(huán),文中的示例代碼講解詳細(xì),具有一定的學(xué)習(xí)價(jià)值,感興趣的小伙伴可以了解一下
    2023-06-06
  • React為什么需要Scheduler調(diào)度器原理詳解

    React為什么需要Scheduler調(diào)度器原理詳解

    這篇文章主要為大家介紹了React為什么需要Scheduler調(diào)度器原理詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-10-10
  • GraphQL在react中的應(yīng)用示例詳解

    GraphQL在react中的應(yīng)用示例詳解

    這篇文章主要為大家介紹了GraphQL在react中的應(yīng)用示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-10-10

最新評(píng)論