React Native は、2015 年 4 月に Facebook によってオープンソース化されたクロスプラットフォームのモバイル アプリケーション開発フレームワークです。わずか 1 ~ 2 年で、多くの企業がこのフレームワークをサポートし、自社のモバイル アプリケーションの構築に採用しました。 プロジェクトの枠組みとプロジェクト構造1. プロジェクトで使用されるテクノロジースタックreact native、react hook、typescript、immer、tslint、jest など。 どれもごく一般的なものなので、詳しくは紹介しません。 2. データ処理では、ReactフックでuseContext+useReducerを使用します。この考え方は redux と一致しており、比較的簡単に使用でき、それほど複雑でないビジネス シナリオに適しています。 const HomeContext = createContext<IContext>({ 状態: デフォルト状態、 ディスパッチ: () => {} }); const ContextProvider = ({ urlQuery, pageCode }: IProps) => { const initState = getInitState(urlQuery, pageCode); const [状態、ディスパッチ]: [IHomeState、IDispatch] = useReducer(homeReducer、initState); 戻る ( <HomeContext.Provider 値 = {{ 状態、ディスパッチ }}> <ホームコンテナ /> </ホームコンテキスト.プロバイダー> ); }; const ホームコンテナ = () => { const { ディスパッチ、状態 } = useContext(HomeContext); ... 3. プロジェクトの構造は以下のとおりです|-ページ1 |-handler // ロジックを処理するための純粋な関数。UT でカバーする必要があります|-container // データ、動作、コンポーネントを統合します|-component // 純粋な UI コンポーネント。コンテンツとユーザー インタラクションを表示しますが、ビジネス ロジックは処理しません|-store // データ構造は 3 層を超えることはできません。また、外部参照と冗長フィールドによってレベルを減らすことができます|-reducer // immer を使用して新しいデータ (不変データ) を返します |-... |-ページ2 |-... プロジェクトの仕様1. ページプロジェクト全体は複数ページのアプリケーションであり、最も基本的な分割単位はページです。 各ページには対応するストアがあり、プロジェクト全体で 1 つのストアが使用されるわけではありません。その理由は次のとおりです。
各ページの外部操作はページコンポーネントで定義されます
ページコンポーネントの主な機能独自のビジネス モジュールに基づいて、抽象化できるすべての外部依存関係と外部相互作用がこのコンポーネントのコードに集中しています。 開発者は、ロジックを記述したりページ間でトラブルシューティングを行ったりするときに、特定のページ + データ ソースに応じて特定のコードを正確に見つけることができるので便利です。 2. リデューサー以前のプロジェクトでは、リデューサーには、データ処理、ユーザーの動作、ログ ポイント、ページ ジャンプ、その他のコード ロジックが含まれる場合があります。 なぜなら、開発者は、コードを書く過程で、リデューサーが特定の処理ロジックの終点(状態を更新した後、イベントが終了する)であることに気づき、それがこれらのことを実行するのに非常に適しているからです。 プロジェクトのメンテナンスと要件の反復により、リデューサーのサイズは増加し続けます。 組織化が不十分でコード量が膨大であるため、コードを調整するのは困難です。 そのようなプロジェクトを維持するのがあなたにとってどれほど苦痛であるかは想像に難くありません。 これを実現するために、リデューサー内のコードでいくつかの減算が行われました。
減速機の主な機能列挙可能な形式で、ページ内のデータを操作するすべてのシナリオを要約します。 React フレームワークに適した独自の機能に加えて、特定のビジネス ロジック読み取り属性が備わっているため、UI コンポーネントに依存せずにページ上のすべてのデータ処理ロジックを大まかに読み取ることができます。 // ディスパッチを2回実行したり、単一フィールドの更新ケースを過度に定義したりしないようにする // このロジックを統合すると、ページ上の動作に関連付けられ、理解と読み取りに役立ちます。ケース EFHListAction.updateSpecifyQueryMessage: リターンproduce(state, (draft: IFHListState) => { draft.specifyQueryMessage = ペイロードを文字列として; ドラフト.showSpecifyQueryMessage = true; }); ケース EFHListAction.updateShowSpecifyQueryMessage: リターンproduce(state, (draft: IFHListState) => { draft.showSpecifyQueryMessage = ペイロードをブール値として; }); 3. ハンドラーここでまず純粋関数の概念を紹介します。 関数の戻り値がパラメータのみに依存し、実行中に副作用がない場合、その関数は純粋関数と呼ばれます。 可能な限り多くのロジックを純粋関数に抽象化し、ハンドラーに配置します。
ハンドラーの主な機能データ ソースからストア、コンテナーからコンポーネント、ディスパッチからリデューサーなどのシナリオでの論理処理を担当します。 さまざまなシナリオにおける論理処理関数の保存場所として、ファイル全体はページプロセス上の関連関係を伴いません。各関数は、その入力と出力の使用シナリオを満たす限り再利用でき、主にコンテナファイルで使用されます。 エクスポート関数 getFilterAndSortResult( フライトリスト: IFlightInfo[], フィルターリスト: IFilterItem[], フィルターシェア: ブール値、 filterOnlyDirect: ブール値、 ソートタイプ: EFlightSortType ){ if (!isValidArray(フライトリスト)) { 戻る []; } ソート関数は、sortType を引数として受け取ります。 const result = FlightList.filter(v => doFilter(v, filterList, filterShare, 1, filterOnlyDirect)).sort(sortFn); 結果を返します。 } 記述(getFilterAndSortResult.name, () => { テスト('getFilterAndSortResult', () => { getFilterAndSortResult(flightList, filterList, false, EFlightSortType.PriceAsc)).toEqual(filterSortResult) を期待します。 }); }); 4. コンテナ上記のプロジェクト構造図からわかるように、各ページにはデータ処理の中心となる基本コンテナーがあります。 この基本コンテナの下で、各サブコンテナは異なるモジュールに従って定義されます。
コンテナの主な機能プロジェクト全体において、コード量が過剰になったりメンテナンスが困難になったりすることを避けるために、さまざまなデータ、UI、ユーザー動作の収束ポイントを関連モジュールから可能な限り分離する必要があります。 コンテナの定義は、ページに表示されるモジュールによって抽象化する必要があります。たとえば、ヘッド コンテナ、コンテンツ コンテナ、フッター コンテナ、その他の一般的な分割方法などです。 一部のページ内の比較的独立したモジュールも、クーポン提供モジュール、ユーザー フィードバック モジュールなど、関連するロジックを集約するために、対応するコンテナーを生成する必要があります。 行動機能に特に注意する
コードの読み取りに便利、モジュールAのフローティング表示ロジック、モジュールBが使用されるときにモジュールが生成される順序、最初にモジュールA、次にモジュールBはAの方法を使用する必要があります
定数OWFlightListContainer = () => { // コンテキストを通じてデータを取得します。const { state, dispatch } = useContext(OWFlightListContext); ... // 初期読み込み中のタイムアウトのカウントダウン useOnce(overTimeCountDown); ... // ユーザーがソートをクリックする const onPressSort = (lastSortType: EFlightSortType, isTimeSort: boolean) => { // ハンドラー内の getNextSortType 関数を参照します。const sortType = getNextSortType(lastSortType, isTimeSort); ディスパッチ({ タイプ: EOWFlightListAction.updateSortType、 ペイロード: sortType }); // ポイント埋め込み操作 logSort(state, sortType); }; // 表示コンポーネントのレンダリング return <.../>; } まとめコーディングのしやすさから読みやすさまで
仕様を定義するのは比較的簡単です。プロジェクトをうまく維持するには、合意に達することを前提にチームメンバーが粘り強く取り組むことが重要です。 実用的な機能をいくつか紹介しますオブジェクトパスに基づいて値を取得する /** * オブジェクトパスに基づいて値を取得します* @param target {a: { b: { c: [1] } } } * @param パス 'abc0' */ エクスポート関数 getVal(ターゲット: 任意、パス: 文字列、デフォルト値: 任意 = 未定義) { ret = ターゲットとします。 キー: 文字列 | undefined = ''; pathList を分割します。 する { キー = pathList.shift(); if (ret && key !== undefined && typeof ret === 'object' && key in ret) { ret = ret[キー]; } それ以外 { ret = 未定義; } } while (pathList.length && ret !== undefined); ret === undefined || ret === null ? defaultValue : ret を返します。 } //デモ const errorCode = getVal(結果、'rstlist.0.type'、0); 設定情報に従って読み取る // 外部と接続する場合、いくつかの固定構造とスケーラブルなデータリストが定義されることがよくあります。 // このような契約に適応し、読みやすさとメンテナンス性を向上させるために、次の関数がまとめられています。 export const GLOBAL_NOTE_CONFIG = { 2: 「払い戻し」、 3: 'ソートタイプ'、 4: '機能スイッチ' }; /** * 設定に従って、attrListの値を取得し、jsonオブジェクト型のデータを返します * @private * 詳細サービスの@member */ エクスポート関数 getNoteValue<T>( noteList: Array<T> | 未定義 | null、 設定: { [_: 文字列]: 文字列 }, キー名: 文字列 = 'type' ){ const ret: { [_: 文字列]: T | Array<T> } = {}; if (!isValidArray(noteList!)) { ret を返します。 } //@ts-無視 noteList.forEach((note: 任意) => { const typeStr: string = (('' + note[keyName]) as unknown) as string; if (!(config内のtypeStr)) { 戻る; } if (note === undefined || note === null) { 戻る; } 定数キー = config[typeStr]; // 値が複数ある場合は配列型に変更します if (ret[key] === undefined) { ret[キー] = メモ; } そうでない場合 (Array.isArray(ret[key])) { (ret[key]をT[]として)push(note); } それ以外 { const first = ret[キー]; ret[key] = [first, note]; } }); ret を返します。 } //デモ // 外部で定義された拡張可能なノート ノード リストの値ロジックに適用可能 const { sortType, featureSwitch } = getNoteValue(list, GLOBAL_NOTE_CONFIG, 'ntype'); 複数条件配列ソート /** * ソートに使用するソート関数を取得します * @param fn 同じ型の要素の比較関数、true はソートの優先順位を意味します */ エクスポート関数 getSort<T>(fn: (a: T, b: T) => boolean): (a: T, b: T) => 1 | -1 | 0 { 戻り値 (a: T, b: T): 1 | -1 | 0 => { ret = 0 とします。 (fn.call(null、a、b))の場合{ 戻り値 -1; } そうでなければ (fn.call(null, b, a)) { 戻り値 1; } ret を 0 として返します。 }; } /** * 複数の並べ替え */ エクスポート関数 getMultipleSort<T>(arr: Array<(a: T, b: T) => 1 | -1 | 0>) { 戻り値 (a: T, b: T) => { tmp にします。 i = 0 とします。 する { tmp = arr[i++](a, b); } while (tmp === 0 && i < arr.length); tmp を返します。 }; } //デモ const ageSort = getSort(function(a, b) { a.age < b.age を返します。 }); const nameSort = getSort(function(a, b) { a.name < b.name を返します。 }); const sexSort = getSort(function(a, b) { a.sex && !b.sex; を返します。 }); //判定条件の順序は調整可能 const arr = [nameSort, ageSort, sexSort]; const ret = data.sort(getMultipleSort(arr)); 上記は、React Native プロジェクト フレームワークの構築に関する私の経験の一部です。React Native プロジェクト フレームワークの構築の詳細については、123WORDPRESS.COM の他の関連記事をご覧ください。 以下もご興味があるかもしれません:
|
<<: CentOS で新しいユーザーを作成し、キーログインを有効にする方法
>>: MySQL 全文あいまい検索 MATCH AGAINST メソッドの例
目次1. 環境2. 準備3. MySQL 8.0.11をインストールするMySQL 8 の公式バージ...
Docker デーモンは、 HTTP_PROXY 、 HTTPS_PROXY 、およびNO_PRO...
序文Samba は、サーバー プログラムとクライアント プログラムで構成され、Linux システム上...
HTML入門ハイパーテキスト マークアップ言語: ハイパーテキスト マークアップ言語ハイパーテキスト...
Rational ClearCase は、コードやその他のソフトウェア開発資産のバージョン管理を実...
目次1. サブクエリとは何ですか? 2. サブクエリはどこに表示されますか? 3. Whereサブク...
コードは次のようになります。 <!DOCTYPE html> <html> ...
序文元のプロジェクトは、パブリックネットワークgitlabに配置されていました。セキュリティ上の理由...
更新: 最近、サーバーがマイニング ウイルスによってハッキングされたことが判明しました。これは、おそ...
1. スクロールの実装原理better-scroll のスクロール原理は、ブラウザのネイティブスクロ...
1. 動作環境vmware14proウブントゥ 16.04LTS 2. 問題の説明vmware14P...
目次私たちが毎日実行している Linux システムとは何でしょうか? LinuxカーネルとGNUシス...
1. 問題の説明セキュリティ上の理由から、新しく構築されたサーバー クラスターでは、指定されたポート...
序文私は less/sass を書くことに慣れていますが、小さなプログラムを開発するときには、まだ ...
序文現在、プロジェクトでは、Axios ライブラリが HTTP インターフェース リクエストによく使...