私たちは最新のフロントエンド開発フレームワークを偶像視しすぎていませんか?

フロントエンドの世界には 2 つの「派」があり、1 つは Vue と呼ばれ、もう 1 つは React と呼ばれます。Vue のメンバーは React を軽蔑し、React のメンバーは Vue を軽蔑し、彼らは自分たちの手にした「教義」こそが真実であり、世界中の苦しみをすべて取り除くことができると信じています。

しかし、絶対的な真実がないのと同じように、完全なシステムのフレームワークもありません。私たちが直面する問題を分析し、直面する困難を解決するための正しい方法を見つけるには、善悪を区別できる目が必要です。私たちは、最新のフロントエンド開発フレームワークに懐疑的な目を向ける必要があります。それらは本当に私たちの問題を解決できるのでしょうか? 答えは「はい」でもあり「いいえ」でもあります。フレームワークは独立して機能することはできず、開発者は大きな変数であり、最大の変数である開発者は、問題が解決できるかどうかを最終的に左右する重要な要素です。

この記事は、最新のフロントエンド フレームワークに対する「賞賛」の現象から始まり、フロントエンド開発がツール自体を重視するあまり、開発者がどのように良いコードを書くかという、コードの品質に影響を与える本質的な問題を無視していることに直面していると指摘します。最後に、解決できると思われるソリューションを示します。ビジネス フロントエンド プロジェクト用のコード アーキテクチャ ソリューション (開発アイデアとも言えます) が、いくつかのアイデアと助けになることを願っています。

1. フロントエンド開発のジレンマ

私の経験から言えば、最新のフロントエンド フレームワークの「崇拝」により、フロントエンド開発がより複雑になり、それが間接的にコード品質の低下とソフトウェア ライフ サイクルの短縮につながります。

私たちが現在直面しているジレンマは、技術的なソリューションが非常に使いやすく効率的である場合もありますが、非常に貧弱であらゆる場所で壁にぶつかる場合もあることです。リラックスした陽気な気持ちで使う人もいれば、イライラするときに使う人もいるでしょうか?一部のプロジェクトでは新しいツールが導入され、開発効率が急激に向上しましたが、他のプロジェクトはますます複雑になり、反復が困難になっていませんか?

その理由は、十分にシンプルで、十分に効率的で、十分に高速で、複雑で変化するビジネス シナリオに対処できる完璧な技術ソリューションを追求してきたからです。これはフロントエンド業界の主流の意識となっており、新しいフレームワークやツールが登場するたびに、前のものよりも優れている、優れているという謳い文句とともに登場し、それを使えばすべての問題が解決するような感覚を与えてくれます。しかし、そのような「人工物」は本当に存在するのでしょうか?私は懐疑的です。ソフトウェア開発は複雑なシステム プロセスです。これは未解決の問題です。この問題を「閉じた」解決策で解決しようとするのは真実に反します。

現代のフロントエンド開発フレームワークはこの問題に直面しており、私たちは 「モグラ塚から山を作る」ような もので、フレームワークの本質がビュー レイヤーのレンダリングの問題を解決することであることを無視して、すべての問題を解決するためにフレームワークを使用したいと考えています。React/VueなどのデータドリブンUIフレームワークの普及により、それが開発上のすべての問題を解決できるかのように、私たちの手の中にある「成果物」になっているように思えます。実際、これも当てはまります。いくつかの問題が解決されていないことがわかった場合は、これらのフレームワークを中心に新しいツールを拡張するだけです。そのため、React ファミリ バケットと Vue ファミリ バケットが存在します。これだけでは不十分な場合は、区別できないデータ ステータス管理ライブラリ、複数のルーティング ジャンプ ソリューション、豊富なコンポーネント コレクション、さまざまな開発およびデバッグ ツール、二次的にカプセル化されたフルスタック フレームワークなど、自由に組み合わせて使用​​できる多数のツール ライブラリも用意しています。待って。状況はますます良くなり、すべてが繁栄し、幸せの向こう側が目の前にあるように見えます。実際のところ、私たちの開発者には大きな負荷がかかっており、私たちのシステムは非常に複雑になっています (個人やチームですら制御できないほど複雑です)。それが 5 年後も稼働しているかどうかは、私たちには考えられません。

ツールを使用すると効率が向上し、作業がより正確になりますが、最終製品の品質に影響を与える最も重要な要素は、ツール自体ではなくその使用方法です。フロントエンドフレームワークは、ビュー層の問題を解決するために使われているという認識が必要で、すべての問題をフレームワークで解決しようとすると、すでに誤解が生じ、本質的な問題を無視していることになります。

2. これは「最新のフロントエンド開発フレームワーク」のせいでしょうか?

先ほど「私の経験から言うと、最新のフロントエンド フレームワークの『崇拝』により、フロントエンド開発がより複雑になり、それが間接的にコードの品質の低下とソフトウェアのライフサイクルの短縮につながっています。」と述べましたが、これは最新のフロントエンド フレームワークの「崇拝」を意味するものではありません。この一連の問題は、フロントエンド フレームワークが原因で発生しました。実際、私はフロントエンド フレームワークがフロントエンド開発にもたらした変化を非常に認識しています。インターフェイス開発の過程での面倒な DOM 操作の問題を解決し、便利な機能をもたらします。コンポーネントベースのコードの再利用および共有メカニズム。これは前向きな技術進歩です。問題の本質はコミュニティがもたらす「崇拝」文化である これは運用の仕組みに起因する問題 フロントエンドフレームワークは重要なノードにすぎない ツールがうまく使われていないからといってツール自体を責めることはできない。

1. なぜ良いものが「悪く」なるのか?

物事を行うには比較的普遍的な原則があります。「小さなことは大きく、大きなことは小さく行う」。フロントエンドのフレームワークを間違えました。「小さなものを大きくする」ことに重点を置きすぎました。それは「モグラ塚から山を作る」とも言えます。大小は相対的なものです。フロントエンド全体を解決するために React/Vue ソリューションを使用する 開発上の問題、これによって良いものが「悪い」ものになる可能性があります。

私は初期の頃に React/Vue などのフレームワークに触れました。正直に言って、その時はとても驚きました。当時、それらは非常に明確な位置づけと問題解決の境界線を持っていました。非常に純粋なビューレイヤーツールでした。 (フレームワークの概念は当時は言及されていませんでした)、シンプルでエレガントです。しかし、繰り返しが繰り返され、コミュニティが火に油を注ぐにつれて、派生ツールやコンセプトがどんどん増えて、徐々に不確かな道に向かって進んでいきます。これらには良い点があることは認めますが、良いものは万能ではなく、適切な場所で適切な方法で使用する必要があり、そうでないと「悪」になってしまいます。

2. フレームワークの急速な開発と開発者の吸収の遅さの矛盾

ソフトウェア開発は複雑なシステム構築プロセスであり、常に開発者が最大の変数となります。フロントエンド インターフェイスが直面する問題は、技術的ソリューションを短期間で迅速に開発することです。作成者の 1% が理論を提案し、参加者の 10% がソリューションを市場に移転します。ほとんどの開発者は受動的に受け入れて使用するという観点に立っています。このプロセスにより、プログラムのプロモーションにおける情報の損失、エラー、およびバリアント プログラムが発生します。同時に、フレームワークの保守者に否定的なフィードバックをもたらし、不具合を引き起こす可能性もあります。

特定のテクノロジーに対する技術的な「宗教」や過度の「崇拝」は、新しいテクノロジーを市場に投入するプロセスを加速し、プロモーションの過程で誤解や曖昧さが発生します。これには意図的でないものもあれば、意図的なものもあります。これらは、現代のフロントエンド フレームワークに現れます。この不健全な成長現象により、フレームワークの使用が極端に推進され、開発者が鋭い技術的感受性と判断能力を確立していない可能性があるため、フロントエンド ビュー全体の出現につながります。 . 景気が良いように見えますが、みんな苦しんでいます。

3. ジレンマを解決するにはどうすればよいですか?

1. 良いものは「悪い」になる可能性があり、悪いものは「良い」になる可能性があります

善意が悪いことをもたらすこともあれば、悪いことが予期せぬ恩恵をもたらすこともあります。これに影響を与える要因の 1 つは、仕事を行う人の大きな「変数」です。物事を成し遂げるためには高い技術力を持ったチームを育てる必要があり、開発者は意識的にコードの品質に注意を払い、技術的なアーキテクチャに気を配り、より良いコードを書くことを考えています。これは最も原始的で最も効果的な方法ですが、もちろん最も困難で最もコストのかかる解決策でもあります。

2. 正のフィードバック機能を備えた運用メカニズムを確立しますか?

このメカニズムは非常に強力で、影響を与える要因によって引き起こされるマイナスの問題を補うこともできます。複雑なシステムでは、単一の要因よりも機構の役割の方が大きく、単一の要因によって生じる誤差を調整することはできますが、単一の要因が動作機構全体に影響を与えることはほとんどありません。
良い運営の仕組みを確立するための良い方法が思いつきませんでしたが、アイデアを持った学生同士で共有することができます。それを構築する方法はまだ見つかっていませんが、これは正しい道であり、検討する価値があると思います。

3. 効果的なトレーニングのために、コードは「書かれています」か?

開発者として、私は基本的に毎日 2 つのことを行っていることに気づきました。1 つはノンストップでコードを記述すること、もう 1 つは継続的な学習です。論理的に言えば、10,000 時間ルールに従って毎日コードを書いていれば、コーディング レベルは向上し続けるはずですが、現実には境界があるようで、その境界に達すると停滞してしまいます。

量的変化から質的変化へのブレークスルーは、持続的な行動の変化によってのみ起こり得るものであり、長期的には効果のないトレーニングが短期的には効果的なトレーニングにつながります。

私は多くの本や記事を読み、多くの共有や講義を聞き、多くの計画を検討し、多くの新しいテクノロジーを使用しました。でも、いつまでも手探りの気持ちはあるし、コツコツ勉強することが成長に繋がるんじゃないでしょうか?

  • どれだけ情報を持っていても、それは知識ではなく、自分の思考で変換し、自分なりの理解で吸収したものが自分の知識であり、それを日々の仕事に活かしていくことが個人の能力です。

  • 人間の思考能力には限界があり、実際の現象は個人が制御できる限界をはるかに超えた複雑かつ多次元のシステムです。正しいアプローチは、小さなものから大きなものへ始めて、単一次元の現象を深く調査し、最終的にそれらを秩序だった方法で組み合わせて複雑な多次元システムを形成することです。

4. 適切なコード アーキテクチャ ソリューションが必要ですか?

私はこれまで数多くの低レベル フレームワーク ツールを設計してきましたが、何が最も難しいかと言えば、フレームワーク設計者は、フレームワーク自体とそれを使用する開発者との対立関係(フレームワークと開発者は対立関係にある)を考慮しなければならないことです。リソースの競合関係。競合するのはソフトウェアの計算量、または単にコードの量です)。この関係を適切に処理し、動的平衡プロセスに到達できるようにすることは、設計者が解決する必要がある本質的な問題です。

ここでは、フロントエンド フレームワークに基づいて拡張し、ビジネス タイプ (重いビジネス ロジック) フロントエンド クラス要件の複雑さの問題を効果的に解決するアーキテクチャ ソリューションを紹介します。

このソリューションはまだ理論設計と検証の段階にあり、実際のビジネスにはまだ実装されていませんが、弁証法的な観点から見ることができます。
企画に賛同する場合は相互にコミュニケーションできますが、気に入らない場合はコメントしないでください。

3 という数字は適切な数であり、システム的な問題を 3 つ解決できれば、アーキテクチャ上のソリューションは優れたソリューションであると考えられます。ここで紹介するソリューションは、次の 3 つの原則に基づいています。

  • 層状の

  • 組み合わせ

  • 一方向の依存関係

大きなレベルでは、階層化の考え方が物事の分類と分離に使用され、各層はインターフェイスを介して直接接続され、システム全体の複雑さを軽減します。たとえば、インターフェイスが期待どおりに機能する限り、クライアントはバックエンド インターフェイスの特定の実装を気にする必要はありません。

各層の実装では、モジュールを組み合わせることで最終的に完全な機能を得ることができます。フロントエンドは高頻度で変更される特性があるため、コード ロジックを編成するにはオブジェクト指向の継承ではなく合成を使用することをお勧めします。継承パターンは安定した構造に適しています。

階層化およびサブモジュールを作成した後、完全なアプリケーションを取得するには、それらを線で接続する必要があります。一方向の依存関係により、ロジックの整理が困難になる無秩序なメッシュ構造の取得を回避できます。

上記の 3 つの原則について考える過程で、既存の MVP アーキテクチャ モデルが非常に優れていることがわかり、MVP アーキテクチャに基づいて少し最適化することで、良いと思われるアーキテクチャ設計が得られました。重要なのは、それを私たち自身の開発思考やビジネス特性とどのように組み合わせるかです。

アーキテクチャの原則に加えて、コード作成の本質を分析してみましょう。コードの品質が低下する原因は何ですか? そしてそれをどうやって解決するのでしょうか?

1. フロントエンドコードが劣化する原因は何ですか?

フロントエンド開発における中心的な問題の 1 つはビューの開発ですが、この問題はフレームワークによって効果的に解決され、DOM を直接操作する必要がなくなり、開発エクスペリエンスが大幅に向上しました。しかし、問題というか誤解は、ビューの開発がすべてであるため、コンポーネント プログラミングに目を向けた結果、すべてのコードが密接に接続されすぎているということです。

ビュー中心のコード編成モデルでは、反復が進むにつれてコードがますます混乱し、論理コードがビュー層に結合されると、すべてのコードが麺一杯のように乱雑になると思います。

  • ビューは頻繁に変更されます。ビューを中心としたコード構成は、ビューをベースにして家を建てるようなものです。その結果、ビューが変更されるたびに、家の他の部分を調整するのに多くの労力を費やす必要があります。コンポーネントは適応します。ベースの変化、それがまさに体全体を動かすということです。

  • ビューをコードの本体として使用する場合のもう 1 つの問題は、ビューがビジネス ニーズを完全に反映できず、一部のビジネス ロジックがビューと無関係であることです。ビジネス ロジックの割合が増加すると、トップヘビー現象が発生します。

  • データ状態管理ツールは、重いビジネス ロジックの問題を解決できるでしょうか? データ状態管理ツールはビュー フレームワークの本質から逸脱しておらず、コンポーネント内のローカル状態管理モードをグローバル状態管理モードに変換しているだけです。中央倉庫に遊休品を置くのと同じように、物品管理の難しさは軽減されないが、乱雑な巨大倉庫を五美のような大型スーパーマーケットに変えるには、科学的かつ合理的な遊休品分類管理計画が重要なポイントとなるはずである。 。

上記の分析に基づいて、解決策の 1 つは、ビュー層を分離し、ビューをロジックから分離し、動的と静的の分離を達成することだと思います。

2. フロントエンドの主な焦点は何ですか?

前述したように、ビュー中心のフロントエンドコード編成方法には欠点もありますが、どのような方法が良いのでしょうか? ビジネスの本質に立ち返ると、ビジネスを中心として、ビューはビジネス プロセスのインターフェイス表現にすぎません。UIは単純なものであり、ビジネスロジックとは言えないと思う フロントエンドのビジネスロジックはビジネスプロセスとインターフェースの接続であるべきであり、プライマリとセカンダリの区別があります。

フロントエンドとして、疑問に思ったことはありますか?フロントエンドとバックエンドの境界が明確でない場合があります。一部の機能はエンドまたはサーバーで実行できます。クライアントとサーバーの対立はクライアント テクノロジーの発展にも影響を及ぼし、サーバーの影が残ります。

フロントエンドでビュー部分が削除された場合、フロントエンドとフロントエンド コードの違いは何になるでしょうか。という質問について考えてみましょう。バックエンドの長期安定した仕組みをフロントエンドにも持ち込むことも考えられます。MVC/MVP アーキテクチャは、バックエンド開発においては比較的成熟したソリューションですが、フロントエンドへの適用も可能だと思います。重要なのは、フロントエンドの既存の技術ソリューションと組み合わせることです。

3. React Hook/Vue Comboposition API によって開発の考え方にどのような変化がもたらされましたか?

React Hook は単なる Class コンポーネントの置き換えではなく、Vue Comboposition API は単なる Options API の構文アップグレードではなく、より根本的なプログラミングの考え方の変化だと思います。
次の SWR サンプル コードを例として取り上げます。

function useUser(id) {
  const { data, error } = useSWR(`/api/user/${id}`, fetcher)


  return {
    user: data,
    isLoading: !error && !data,
    isError: error,
  }
}

以上のことから、useSWR の導入は通常の util 関数の導入と同じであることがわかりますが、ここで考慮されるのはコンポーネントの初期化時に何をするかではないでしょうか。コンポーネントが更新されたら何をしますか? 代わりに、純粋にデータの変化プロセスを考えることになり、計算問題になります。これは実際には、ビューとロジック層を分離し、ビジネス ロジックを useSWR フック (リクエスト、中間状態の読み込み、エラー処理を含む) に集中させるというアイデアです。しかし、残念ながら現在のフックは完璧ではなく、条件文で使用できない、繰り返しレンダリングできないなどの問題がまだ残っています。Vue Comboposition API はまだ主流のメソッドになっておらず、すべてがまだ調査中です。コミュニティにはこれに基づいたデータステータス更新ソリューションがすでにたくさんありますが、将来的にはこれに基づいたフロントエンドコードアーキテクチャソリューションがさらに登場すると思います。

4. ビジネスロジックを核としたアーキテクチャソリューション - (A)

このプランを仮に A と名付けます。プラン A の適用シナリオは主に中規模のページです。分割されたサブモデルおよびサブロジック モジュールの数は 20 を超えません。それほど多くないように見えますが、実際には満たしています。ほとんどのページの開発ニーズ。

上記のシナリオと一致しない場合は、主に各層内の順序的な組み合わせ計画の問題と各層間の通信方法の最適化により、計画 A に基づいて調整する必要があります。

データ層の論理層が大きすぎる場合は、DDD を直接使用することを検討できます。複雑なシナリオに直面すると、アーキテクチャのガイダンスがない場合よりも、理想的ではないアーキテクチャ ソリューションを採用する方が良いでしょう。

4.1. MVP モデルに基づく進化的アーキテクチャの概要

9c848d86d08ffa212d4c2e25bc421277.png

  1. さまざまな部分間の通信は双方向です。

  2. View と Model の間には接触がなく、どちらも Presenter を介して渡されます。

  3. View は非常に薄く、ビジネス ロジックを展開しません。これは「パッシブ ビュー」と呼ばれます。つまり、主導権を持ちません。一方、Presenter は非常に厚く、すべてのロジックがそこに展開されます。

次の階層化アーキテクチャに拡張できます (MVP の利点を維持)。

25d81882302b11133edd608320c3ac72.jpeg

  • MVP に基づく階層化アーキテクチャ (階層化の境界を理解することは、階層化ソリューションが効果的かどうかの重要な要素です) 

    • データ層 (モデル) - ビジネス ロジックが依存するデータ エンティティ (DDD エンティティの定義を参照してください)

    • ロジック層 (プレゼンター) - ビジネス ロジックを処理します

    • ビュー レイヤー (View) - フロントエンド インターフェイスの対話を処理します。

  • 各層は組み合わせによって完全な機能を形成します 

    • データ層は複数のサブモデルで構成されます

    • 論理層は複数のサブ論理モジュールで構成されます (結合されたメイン論理モジュールは他の層と対話します)

    • ビューレイヤーは複数のコンポーネントで構成されます

  • 単一の依存関係により結合が減少し、プロセスがより明確になります。

4.2. プラン A のいくつかの欠点の分析

1つ目は、階層構造による判断力の必要性ですが、実際に実践してみると、境界があいまいでどの層にコードを書けばいいのか分からなくなる、ということがよく起こります。このような状況に対しては、まず「完成」を求め、次に「完璧」を求めるという考え方で、自チームに合った正しく合理的な方法を実践で積み重ねていくことができると思います。

2 つ目は過剰な抽象化で、これもほとんどの計画に見られます。1 ステップで完了することが明らかな事柄でも、ルールに従わなければならない場合があります。

ゾウを冷蔵庫に入れるには、いくつかの手順が必要です。

  1. 冷蔵庫を開ける

  2. ゾウが冷蔵庫に入る

  3. 冷蔵庫を閉める

ワンステップで行うこともでき、ゾウは自分で冷蔵庫に入ります。

上記の例から判断すると、問題はありませんが、実際のシステムはさらに複雑になり、複数の参加オブジェクトが関与する 10 を超える完全なステップが存在する可能性があり、参加オブジェクト間の相互作用が存在する可能性があるため、非常に効果的です。厳格な取扱説明書に段階的に従うことが必要です。最終的には、ビジネス シナリオを具体的に分析し、それがアーキテクチャ計画と一致するかどうかが問題になります。評価基準の統一が難しく、評価コストが高すぎる場合、つまり、使用に適しているかどうかが簡単に判断できない場合は?無くても大丈夫なようですが?使っても大丈夫ですか?使用する必要がない明確な理由がない場合は、直接使用することをお勧めします。そうでない場合は、使用する必要はありません。

もう一つのマイナス影響は、避けられない枠組みコスト(研究開発費、保守費、プロモーション費、ビジネスアクセス費)の問題です。

5. まとめ

  • 最新のフロントエンド開発フレームワークの出現により、フロントエンドの世界に変化が生じていますが、それをあまり「崇拝」することはできません。主に複雑なインタラクティブ開発の問題を解決するものであり、ビジネス ロジックの複雑なニーズの開発には完璧ではありません。純粋なビュー レイヤー ソリューションとして使用できます。

  • 完全に完璧な技術的解決策はありません。関係する影響要因が多すぎます。その中で開発者は大きな「変数」です。優れたアーキテクチャ的思考を持つ開発者によって書かれたコードは、優れたコードである可能性があり、それ自体がテクノロジーです。アーキテクチャに関するフィードバック提案。技術ソリューションの設計出力は、汎用的で使いやすいソリューションです。

  • 小規模から大規模、そして大規模から小規模へと普遍的な技術ソリューションを設計します。すべての問題ではなく中核問題の解決を追求し、開発者との敵対関係のバランスを保ちます。許容範囲内のマイナスコストはプログラム全体の決定に影響しません。

6. 例

以下は、コード アーキテクチャの分割のより現実的な例です。

cbd41e3ddf7cee361a11c25a32a2bc4f.png

上記の例のように、商品データを取得してページ上にリスト形式で表示する必要がありますが、プランAによれば、この機能は次のように分解できます。

1. 従来の疑似コードの記述:

export default class PortalPage extends Component {
    registerModels () {
        return [
            {
                namespace: 'PortalGoodModel',
                state: {
                  pageNum: 1,
                  pageSize: 10,
                  hasNextPage: true,
                  goodsData: []
                },
                reducers: {
                  updateGoodsData (state, payload) {
                    // 更新数据操作
                  }
                }
              }
        ]
    }
  
    state (state) {
        return {
          ...state,
          // 是否有数据,纯 UI 内部状态
          noResultPageVisible: state.PortalGoodModel.goodsData.length
        }
    }
  
    ready () {
        this.getPageData();
    }


    async getInfo () {
        const locationInfo = await this.dispatch({type: 'PortalLocationModel/updateInfo'})
        return locationInfo;
    }


    async getPageData (type) {
        const { adCode, userAdCode, longitude, gpsValid } = await this.getInfo();
        
        if (!(adCode && userAdCode && longitude) || !gpsValid) {
            // 定位失败
            if (type === 'onErrorRetry') {
                utils.toast('请开启定位');
                this.dispatch({
                    type: "PortalLocationModel/updateLocationStatus",
                    value: 'error'
                })
            } 
        } else {
            this.dispatch({
                type: "PortalLocationModel/updateLocationStatus",
                value: 'success'
            });
            const requestParams = utils.getRequestParams({
                pageData: this.$page.props,
                location,
            });
    
            const res = await fetch(requestParams);
            if (res.code !== 1) {
                // 请求错误处理
            } else {
                const result = this.processResult(res);
                this.dispatch({
                  type: 'PortalGoodModel/updateGoodsData',
                  ...result
                });
            }
        }
    }
}

上記のコードを観察すると、データ モデルの操作、ビジネス ロジック、およびビューのコードが getPageData でソフト化されていることがわかります。これはすでに単純化されていますが、現実のビジネスではさらに多くのロジックが非線形構造で絡み合い、無意識のうちに複雑さが増していきます。

2. アーキテクチャ分割疑似コード

2.1 モデル層の例

次の製品モデルを構築します。モデル レイヤーとロジック レイヤーの本質的な違いは、モデル レイヤーがよりアトミックなデータ操作であり、バックエンド データベースやドメイン モデル内のエンティティの抽象定義と比較できることです。

ロジック層はモデル層に依存して完全なビジネス ロジックを形成しますが、モデル層は独立しており、ロジック層の何にも依存しません

// 这里使用 dva 做为建模工具,你可以用其它的状态工具或者纯 js 对象都可以
export default {
  namespace: 'PortalGoodModel',
  state: {
    pageNum: 1,
    pageSize: 10,
    hasNextPage: true,
    goodsData: []
  },
  reducers: {
    updateGoodsData (state, payload) {
      // 更新数据操作
    }
  }
}

ここで言及しておく価値があるのは、フロントエンド開発の学生はインタラクティブ モデル (インターフェイスに非常に近い) の考え方により適応できる可能性があるため、ここで独立したサブモデルを確立することは必須ではないということです。コードの論理的な分離がより必要だと思います。

2.2 論理層の例

ロジック層とビュー層の境界の判断基準は、ビジネスロジックでその状態が必要かどうかであり、必要な場合はモデル層でモデル化し、依存関係ロジックはロジック層で記述し、ビューレイヤーは、レンダリングに必要な UI 状態に変換する必要があります。

  • ビュー レイヤで使用する getPageData インターフェイスを提供します

  • 地理的位置の取得と製品データの取得のためにサブロジック モジュールを分割する

  • サブ論理モジュール間、および論理層とビュー層間の通信はインターフェイスの形式で行われます。

以下は、ビューとの通信と対話を担当するコア ロジック モジュールです。

// 该 presenter 会与视图关联,提供给视图使用的接口
// PortalPresenter.js
export default class PortalPresenter {
    getPageData (obj) {
        // 获取地理位置信息是 PortalLocationPresenter 做的,而拿到地理信息后
        // 该怎么去用则是另一个模块的事情
        this.$PortalLocationPresenter.onLocation({
            success: () => {
                this.$PortalGoodsPresenter.fetchData(obj)    
            }
        })
    }
}

地理情報処理モジュール:

// PortalLocationPresenter.js
export default class PortalLocationPresenter {
    async getInfo () {
        const locationInfo = await this.dispatch({type: 'PortalLocationModel/updateInfo'})
        return locationInfo;
    }


    async onLocation (obj) {
        const { adCode, userAdCode, longitude, gpsValid } = await this.getInfo();
        // 定位失败
        if (!(adCode && userAdCode && longitude) || !gpsValid) {
            this.dispatch({
                type: "PortalLocationModel/updateLocationStatus",
                value: 'error'
            })
            obj?.fail();
        } else {
            this.dispatch({
                type: "PortalLocationModel/updateLocationStatus",
                value: 'success'
            })
            obj?.success();
        }
    }
}

以下は、製品データ ロジックを処理するためのサブモジュールです。

export default class PortalGoodsPresenter {
    name = 'PortalGoodsPresenter'
    async fetchData (obj) {
        // 请求参数处理
        const requestParams = utils.getRequestParams({
            pageData: this.$page.props,
            location,
        });


        const res = await fetch(requestParams);
        if (res.code !== 1) {
            obj?.fail()
        } else {
            const result = this.processResult(res);
            this.dispatch({
              type: 'PortalGoodModel/updateGoodsData',
              ...result
            });
          obj?.success();
        }
    }
}

2.3 ビューレイヤーの例

  • 純粋な UI レンダリング操作を実行し、ui = fn(state) の本質に戻ります。

  • ビュー層は、ロジック層によって提供されるデータ取得インターフェイスを使用してデータを取得します。

  • 非同期データの取得に関連する UI 操作は引き続きビュー レイヤで処理されます。 

    • 位置決めに失敗した場合のトースト プロンプト

    • たとえば、空のデータを含む UI を表示するかどうか (この UI ロジック層は決して使用されません)

{
  state (state) {
    return {
      ...state,
      // 是否有数据,纯 UI 内部状态
      noResultPageVisible: state.PortalGoodModel.goodsData.length
    }
  }
  ready () {
    this.getPageData();
  },
  getPageData (info = {}) {
    this.$presenter.getPageData({
      type: info.type,  // 获取数据类型
      fail (errorInfo) {
        if (errorInfo.type === 'locationError') {
          // from 代表调用类型
          if (info.from === 'onErrorRetry') {
            utils.toast('请开启定位');
          }
        }
      }
    });
  }
}

分割されたコードはより焦点が絞られ、各層の動作が分離され、依存関係がより明確になります。

推奨関連書籍:ビジネス開発からアーキテクチャ設計を学び理解する

詳細については、「Amap テクノロジー」をフォローしてください

おすすめ

転載: blog.csdn.net/amap_tech/article/details/130878098