この記事では、州および市のカスケードにおける同様のカスケード機能に関する最近の実装アイデアを紹介します。責任、パフォーマンス、および行動を可能な限り分離するために、この関数は2つのコンポーネントに分割され、単一のリンクリストを使用してキーカスケードロジックを実装します。次のセクションにはデモ効果があります。これは非常に一般的な機能ですが、この記事の実装ロジックは明確であり、コードは理解しやすいです。それは州および市のカスケードのセマンティクスから分離されており、パフォーマンスと行動の分離を考慮しています。この記事の内容があなたの仕事にいくつかの参照値をもたらすことができることを願っています。それを読んで修正してください。
カスケードカスケード操作
CascadeType。 Cascade Persistence(Save)操作を保持します
CascadeType。カスケードアップデート(MERIG)操作をマージします
CascadeType。カスケードの更新操作を更新し、クエリのみを取得して操作を取得します
CascadeType。 cascade削除操作を削除します
CascadeType。上記のすべての操作すべてをカスケードします
フェッチクロールの負荷を遅らせるかどうか、デフォルトは最初の側がすぐにロードされ、より多くの側が遅延荷重があることです
マッピングされた関係のメンテナンス
mappedby = "dartid"とは、Children ClassクラスのParentID属性が関係を維持するために使用されることを意味します。この名前は、ChildrenクラスのParentID属性名とまったく同じでなければなりません。
また、親クラスのコレクションタイプがリストまたは設定されている必要があり、アレイリストに設定できないことに注意する必要があります。そうしないと、エラーが報告されます。
デモンストレーション効果(コードダウンロード、注:この効果では、HTTPが実行される必要があります。さらに、効果のデータはシミュレートされたデータであり、実際には背景によって返されないため、州、都市、郡のプルダウンデータは同じです):
注:この記事では、以前のいくつかの関連するブログの技術的実装を使用しています。必要な場合は、以下のリンクをクリックして学習できます。
1)JavaScriptの継承実装の詳細な説明:class.jsを提供して、JavaScriptクラスと建設クラスの間の継承関係を定義します。
2)コンポーネントをサポートするためのjQueryスキルdomのようなイベント管理をサポートする:eventbase.jsを提供して、任意のコンポーネントインスタンスをDOMのようなイベント管理機能を提供する。
3)jQueryのajaxおよびajaxキャッシュプロキシコンポーネントの二次カプセル化:ajaxcache:ajax.jsとajaxcache.jsを提供し、jQueryのAjaxコールを簡素化し、クライアントリクエストのキャッシュプロキシを簡素化します。
まず、この関数の要件について詳しく知りましょう。
1。機能分析
この関数は、3つのカスケードアイテムを含むカスケードコンポーネントによって示されています。
1)各カスケード項目は、入力プロンプトとして使用するオプションが必要になる場合があります。
この場合、空のオプションは、各カスケードアイテムのデータリスト(つまり、入力によって促されるもの)で選択できます。
また、入力プロンプトとして使用する必要がない場合があります。
この場合、各カスケードアイテムのデータリストで選択できるデータオプションのみを選択でき、空のオプションは選択できません。
2)現在のページがデータベースからクエリをしており、カスケードコンポーネントに対応するフィールドに値がある場合、クエリの値はカスケードコンポーネントにエコーされます。
クエリで見つかった対応するフィールドに値がない場合、ポイント1)の要件で説明されている2つの状況が表示されます。
3)各カスケードアイテムは、データ構造に単一のリンクリスト関係を形成します。後者のカスケードアイテムのデータリストは、以前のカスケード項目によって選択されたデータに関連しています。
4)パフォーマンスの問題を考慮して、各カスケードアイテムのデータリストはAjaxによって非同期に表示されます。
5)カスケードコンポーネントの初期化が完了した後、最初のカスケードアイテムのリストが自動的にロードされます。
6)現在のカスケードアイテムが変更されたら、直接的または間接的に関連付けられているすべてのカスケードアイテムのデータリストをクリアします。同時に、以前のカスケードアイテムの後の値が空でない場合、それに直接関連付けられている次のカスケードアイテムのデータリストは自動的にロードされます。カスケードアイテムのデータリストをクリアするときは、注意してください。カスケードアイテムが入力プロンプトオプションを表示する必要がある場合は、クリア時にオプションを保持する必要があります。
7)パフォーマンスの問題を完全に考慮し、重複した負荷を避ける必要があります。
8)フォームの提出の問題を考慮して、カスケードコンポーネントのカスケード項目が変更された場合、カスケードコンポーネントによって選択された値は、テキストフィールドを介したカスケードコンポーネントの値のサブミットを背景に容易にするために、隠されたテキストフィールドに反映されなければなりません。
関数はほぼ上記のとおりです。
2。実装のアイデア
1)データ構造
他のコンポーネントとは異なるのは、バックグラウンドのデータに依存関係があることです。私が検討するデータ構造はよりよく実装されています:
{"id":1、 "text": "beijing"、 "code":110000、 "dartid":0}、{"id":2、 "text": "hebei province"、 "code":220000、 "derid":0}、{"id":3、 "text": "" ":" 330000、 "parentid"IDはデータの一意の識別子であり、データ間の関連関係はderparentIDを介して構築されます。テキストとコードはすべて通常のビジネス分野です。このデータ構造に従うと、カスケードデータリストのインターフェイスをクエリするのは非常に簡単です。
//最初のカスケードアイテム/API/カスケードのリストを確認しますか?dartid = 0 //最初のカスケードアイテム/API/カスケードによって選択された値に基づいて2番目のカスケードアイテムのリストを確認しますか?
この構造は、背景にも簡単に処理できます。それらは構造的には木形のテーブル構造ですが、クエリはすべて単一層であるため、簡単に実装できます。
また、この構造がデータのインターフェイスとパラメーターを1つに統合するのに役立つことを以前のクエリデモンストレーションから見ることができます。これは、コンポーネント開発に非常に便利なものです。このデータ構造をバックグラウンドから取得した後、<オプション値= "beijing" data-param-value = "1"> beijing </option>など、各データをオプションに解析します。これにより、データリストのドロップダウンディスプレイを完了するだけでなく、選択フォーム要素の関数を介して現在のカスケードアイテムの選択された値を収集できます。最後に、Cascadeアイテムが変更されたら、選択したオプションを取得し、Data-Param-Valueの値をParentIDパラメーターとして使用して、次のカスケードアイテムのリストをロードすることもできます。これは、コンポーネントのデータクエリと解析のカスケードのアイデアでもあります。
ただし、ここで考慮する必要があるのは、柔軟性の問題です。実際のプロジェクトでは、Cascadingコンポーネントのデータ構造は、ID ParentIDなどの同様の関連関係に従って定義できますが、そのフィールドは必ずしもID ParentIDテキストコードと呼ばれるわけではなく、他のフィールドである可能性があります。言い換えれば、データをオプションに解析する場合、オプションテキストと値に使用されるフィールド、およびdata-param-value属性に使用されるフィールドの値は不確かです。データのクエリをクエリするときに使用されるパラメーター名dameidは死にません。バックエンドスタッフが最初にクエリインターフェイスを書き込み、別の名前を使用する場合、パラメーター名を変更して展開する必要があるため、誰かにパラメーター名を変更するように依頼することはできません。これはフロントエンドよりも面倒です。実際のプロジェクトのデータの最初の層の括弧は空または-1である可能性があるため、derperid = 0の値を修正できません。これらのことはオプションとして設計する必要があります。一方では、デフォルト値が提供され、外部設定も実際の状況に応じて予約されています。たとえば、この記事の最終実装では、このオプションは次のように定義されています。
テキストフィールド:「テキスト」、// <オプション>要素に表示される返されたデータのフィールド名
ValueField: 'Text'、//返されたデータのフィールド名は<option>要素の値に設定されます
Paramfield: 'id'、//データQueryインターフェイスを呼び出すと、背景に渡されるデータに対応するフィールド名
Paramname: 'ParentID'、//データQueryインターフェイスを呼び出すと、URLの後にデータのパラメーター名が渡されます
defaultParam: ''、//最初のカスケードアイテムを照会する場合、背景に渡される値は一般に0、 ''、または-1などです。
2)HTML構造
以前の機能分析の第1条によると、カスケードコンポーネントの初期HTML構造には2つのタイプがあります。
<ul id = "licenselocation-view"> <li> <select> <option value = "">州を選択してください</option> </select> </select> </li> <li> <select> <option value = ""> city> </li> <li> <select> <option value = ">
または
<ul id = "companylocation-view"> <li> <select> </select> </li> <li> <select> </select> </li> <li> <li> <select> </select> </li> </ul>
これら2つの構造の唯一の違いは、入力プロンプトとして使用されるオプションが構成されているかどうかです。また、この空のオプションが必要な場合、値属性を空に設定する必要があることにも注意してください。そうしないと、この空のオプションはフォームを送信するときにオプションのプロンプト情報を背景に送信することに注意してください。
これらの2つの構造の最も重要なことは、ULとLIとは何の関係もない選択要素です。 ULとLiはUIに使用されます。選択要素にはセマンティクスがなく、どの州が都市であり、地区または郡であるかを特定する必要はありません。機能的に言えば、セレクトはカスケードアイテムを表します。これらの選択が定義されている場所は関係ありません。カスケードアイテムが構成されている要素を選択するカスケードコンポーネントに伝える必要があります。コンポーネントに通知する必要がある唯一のことは、これらの選択要素のシーケンスですが、これは通常、HTMLの要素のデフォルト順序によって制御されます。この構造は、コンポーネントの関数をできるだけ動作から分離するのに役立ちます。
3)責任の分離と単一のリンクリストの使用
前の部分から、このカスケードコンポーネントが責任に応じて分割されている場合、2つのコアコンポーネントに分割でき、1つは全体的な機能と内部カスケードアイテムの管理(CascadeView)に責任があり、もう1つはカスケードアイテム(Cascadeitem)の機能的実装に責任があることがわかります。さらに、より便利にカスケードロジックを実装するためには、リンクされたリストを介してすべてのカスケードアイテムを接続するだけです。パブリッシュサブスクライブモードを介して、後者のカスケードアイテムは、以前のカスケードアイテムが変更されたというメッセージを購読します。現在のカスケードアイテムが変更されると、関連するロジックを処理するための後続のカスケードアイテムに通知するメッセージが投稿されます。リンクリストの役割を通じて、このメッセージは最後のカスケードアイテムまで渡される場合があります。あなたがそれを写真で説明するならば、それはほぼこのようになります:
私たちがする必要があるのは、良いニュースのリリースと配信を制御することです。
4)フォームの提出
カスケードコンポーネントの値をバックグラウンドに便利に送信するために、カスケードコンポーネント全体を全体として扱うことができ、外部イベントがすべてのカスケードアイテムの値を取得できる外部に変化したイベントが提供されます。 onChangedイベントを公開するときは、複数のカスケードがあるため、このイベントはカスケードが変更されたときにのみトリガーできます。
5)ajaxキャッシュ
このコンポーネントでは、Ajaxキャッシュの2つのレベルを考慮する必要があります。最初のものはコンポーネントレベルです。たとえば、最初のカスケードアイテムを北京に切り替えました。この時点で、2番目のカスケードアイテムは北京のデータをロードしました。次に、最初のカスケードアイテムを北京からヘベイ、そして北京に切り替えました。この時点で、2番目のカスケードアイテムには、北京の関連データリストがまだ表示されます。リストが最初にロードされたときにデータをキャッシュした場合、今回はAJAXリクエストを開始する必要はありません。 2番目はAjaxリクエストです。レベルでは、ページに複数のカスケードコンポーネントがある場合、最初に最初のカスケードコンポーネントの最初のカスケードアイテムを北京に切り替え、ブラウザはAJAXリクエストを開始してデータをロードします。 2番目のカスケードコンポーネントの最初のカスケードアイテムを北京に切り替えると、ブラウザはデータをロードする別のリクエストを送信します。最初に最初のコンポーネントの最初のAJAX要求によって返されたデータをキャッシュすると、2番目のコンポーネントが同じパラメーターを使用して同じインターフェイスを要求する場合、以前のキャッシュを直接使用して結果を返します。これにより、AJAX要求も削減できます。 Ajaxキャッシュの2番目のレベルは、上記の「JQuery AjaxおよびAjax Cacheプロキシコンポーネントの二次カプセル化:Ajaxcache」に依存します。コンポーネントの場合、第1レベルのキャッシュは内部でのみ実装されますが、第2レベルのキャッシュ実装はそれに対して透明であり、使用するAjaxコンポーネントにキャッシュの関数があることを知りません。
3。実装の詳細
最終実装には、CascadeView、CascadeItem、およびCascadepublicDefaultsの3つのコンポーネントが含まれます。最初の2つはコンポーネントのコアであり、最後の2つはいくつかのオプションを定義するために使用されます。その機能については、cascadeitemのコメントで詳細に説明されています。さらに、いくつかの重要なコードの役割を説明する非常に詳細なコメントが次のコードにあります。以前の要件に基づいてコードを見ると、比較的理解しやすいはずです。以前はテキストを使用していくつかの実装の詳細を説明していましたが、後でこの方法は少し感謝していると徐々に感じました。まず、詳細レベルの言語を整理するのは簡単ではありませんでした。時々私は自分の意味を表現しませんでした。私は明らかに何かを明確に説明したかったのですが、それはさらに混乱していることが判明しました。少なくとも、私が書いたものを読んだとき、私はこのように感じるでしょう。第二に、開発者自身がソースコードを読むことができ、ほとんどのアクティブな開発者は、他の人のコードについて考えることで実装のアイデアを理解することをいとわない。だから私は注釈を使用して、代わりに実装の詳細を説明します:)
cascadepublicdefaults:
define(function(){return {url: ''、// data query interface textfield: 'text'、// field name valuefield: 'text'、// <オプション>要素に表示されるフィールド名でデータを返す、<paramfield: 'text'、//フィールド名のデータを返すデータを返します。バックグラウンドに渡されるデータのパラマネームは次のとおりです。//データクエリインターフェイスを呼び出すと、URLの後に渡されたデータのパラメーター名はdefaultParam: ''、//最初のカスケードアイテムを照会する場合、背景に渡される値は一般に0、 '' ''、または-1などです。 (次のような入力プロンプトとして使用されます。州を選択してください)、Trueの場合、デフォルトの最初のoptionSolveajaxはカスケードアイテムをリロードするときにクリアされません:function(res){return Res;} //カスケードアイテムはデータをロードするときに非同期リクエストを送信するため、このコールバックは浅いリクエストに使用されるために使用されます)。cascadeview:
define(function(require、exports、module){var $ = require( 'jquery'); var class = require( 'mod/class'); var eventbase = require( 'mod/eventbase'); var publicdefaults = require( 'mod/cascadepublicdefaults'); cascadeItemコンポーネント*/var defaults = $ .extend({}、publicdefaults、{$ elements:// cascadedアイテムJQオブジェクトの配列、データ内の要素の順序は、カスケードされたバイリスパレーターの順序を表します。地区、Chaoyang地区の価値: ''、// ValueSeparatorによって区切られた文字列は、開始時の各選択の値を表します。 this.base(); var opts = this.options = this.getoptions(option)、this.items = []、this = opts。 {var $ el = $(this); // cascadeitemコンポーネントをインスタンス化し、各インスタンスのprevitemプロパティを前のインスタンスに指してください$ .trim(values [i])})); items.push(cascadeitem); //各カスケードインスタンスの変更は、Cascadeviewコンポーネントの変更イベントをトリガーします//アウトサイドは、このコールバックでビジネスロジックを処理できます。 {thit.trigger( 'chander.cascadeview'、that.getValue();});} (){return defaults;}、getItemoptions:function(){var opts = {}、_options = this.options; for(var i in publicdefaults){if(publicdefaults.hasownproperty(i)&& in _options){opts [i] = _ options [i] ValueSeparator //空のカスケードアイテムの値によって区切られた文字列であるすべてのカスケードアイテムはGetValue:function(){var value = []; this.items.foreach(var val = $ .trim(item.getValue(); val!= ''&&b value.push(val);}); value.join(this.options.valueseparator);}}、extend:eventbase}); return cascadeview;});cascadeitem:
define(function(require、exports、module){var $ = require( 'jquery'); var class = require( 'mod/class'); var eventbase = require( 'mod/eventbase'); var publicdefaults = require( 'mod/cascadepublicdefaults'); = new ajaxcache();/*** cascadeItemコンポーネントは外部で直接使用されないため、オプションの一部が外部で使用されないため、Cascadeviewコンポーネントがパブリックになると、Cascadeviewコンポーネントを通過する場合もあります。 publicDefaultsはcascadeitem*/var defaults = $ .extend({}、publicdefaults、{previtem:undefined、//以前のカスケードアイテム値を指します: '' // var cascadeitem = class({instancemembers:{init:eel、chments untse options(eel、chmets ems options) this.base。 $ el.on( 'change'、function select要素のプロキシ{that.trigger( 'change.cascadeitem');});コンテンツ自体、コンテンツは、hascontent && that.clear(); //最初のカスケードアイテムではなく、以前のカスケードアイテムが有効なオプションを選択しない場合、(that.previtem.getvalue()); $ .trim(this.options.value); value!== '' && this.one( 'render.cascadeitem'、function(){// $ el.val(value.split( '、')) (options){return $ .extend({}、this.getDefaults()、options);}、getDefaults:function(){return defaults;}、clear:function(){$ el = this。$ el.val( ''); if(this.options.keepfirstuttion)オプション$ el.children()。フィルター( ':gt(0)')。 this.options、paramvalue、that = this、datakey; // datakeyはキャッシュキャッシュ時に使用されるキー名// opts.defaultparam; datakey = 'root';} else {paramvalue = this.previtem.getParamvalue(); datakey = paramvalue;} //データキャッシュにデータがロードされたかどうかを最初に確認します。 params = {}; params [opts.paramname] = paramvalue; ajax.get(opts.url、params).done(function(res){// resolveajax data; that.render(data);});}}、rewender:function(data){var html = []、opts = this.options; data.foreach(item(item){html.push(['<option value = "'、item [opts.valuefield]、 '" data-param-value = "' 'data-param-value ="オプション項目[opts.paramfield]、 '">'、item [opts.textfield]、 '</option>']。join( ''));}); //最初のオプションに影響を避けるために付録の形式で動的に追加します。 this.trigger( 'render.cascadeitem');}、getValue:function(){return this。$ el.val()、getParamValue:function(){return this。$ el.find( 'option:selected')。4。デモの指示
コードの構造を示します。
フレーム化されているのは、デモンストレーションの関連部分です。 html/regist.htmlは効果を示すページであり、js/app/regist.jsはデモ効果JSへのエントリです。
define(function(require、exports、module){var $ = require( 'jquery'); var cascadeview = require( 'mod/cascadeview'); function publicsetcascadeview(fieldname、opts){this.cascadeview = new cascadeview({$ election:$( ' +' + fieldname + '-biew +' -view + '-biew + '../api/cascade.json'、onchanged:onchanged、opts.values、keepfirstoption、resolveajax:function(res){if(res.code == 200){return resid res.data} $( 'input [name = "licenselocation"]')、keepfirstoption:true、setcascadeview、onchanged:function(e、value){location_views.licenselocation。$ input.val(value)}、companylocation:{$ input: 'companylocation: SetCassadeView:publicseTcascadeview、onchanged:function(e、value){location_views.companylocation。$ input.val(value)}}}; location_views.companylocation.setcascadeview( 'companylocation'、{values:location_views.companylocation。$ input.val()});});ページに複数のカスケードコンポーネントがあるため、上記のコードの変数Location_Viewsの関数に注意してください。この変数は、実際にはポリシーモデルを介して同様の方法で管理されています。これを行わない場合、重複コードを簡単に生成できます。このフォームは、ビジネスロジックが処理される場所など、エントリファイルのビジネスロジックの分離とカプセル化をより助長します。
5。その他
これはおそらく、会社によって書かれた最後のブログです。 2日間で新しいユニットで仕事に行かなければなりません。通常の仕事のアイデアを録音する余暇がたくさんあるかどうかはわかりませんが、少なくともブログを書く習慣を身につけてきました。将来時間がない場合は時間を絞ります。今年の目標は、主に知識を広げ、コードの品質を向上させることです。その後のブログは、コンポーネント開発のカテゴリに登場します。今後もwulin.comのウェブサイトに注意を払い続けることができることを願っています!