この記事では、Webページ上の一般的な画像の実装アイデアを紹介して、アップロード後にページ上の小さな画像プレビューを直接生成します。この関数には特定の適用可能性があることを考慮すると、関連するロジックはImageUploAdviewコンポーネントにカプセル化されます。実際の使用効果を使用して、次の段落でGitレンダリングを表示できます。このコンポーネントを実装するプロセスでは、継承ライブラリclass.jsなどの以前のブログで紹介した関連コンテンツを使用し、任意のコンポーネントのイベント管理ライブラリEventbase.jsを使用します。読んでコミュニケーションをとることを歓迎します。
デモンストレーション効果:
注:デモンストレーションのコードはすべて静的であるため、ファイルによってアップロードされたコンポーネントはSettimeOutによってシミュレートされますが、その呼び出し方法は、実際の作業でアップロードコンポーネントを使用する場合とまったく同じであるため、デモンストレーション効果のコード実装は実際の機能要件に完全に沿っています。
私の以前のブログのアイデアによると、最初にこのアップロードプレビュー関数の要件を紹介しましょう。
1。要件分析
以前のデモンストレーションレンダリングによると、分析要件は次のとおりです。
1)最初のアップロード領域では、1つのクリック可能なアップロードボタンのみが表示されます。このボタンをクリックすると、アップロードされた画像が後続のプレビュー領域に表示されます。
2)アップロードされた画像がプレビュー領域に追加されたら、ボタンを削除して削除できます。
3)アップロードされた画像の総数が一定の制限に達すると、たとえば、デモンストレーションのアップロード制限は4です。アップロードボタンを削除します。
4)アップロードされた画像の総数が一定の制限に達すると、削除操作によって特定の画像が削除された場合、アップロードボタンを表示する必要があります。
上記の要件が表示されます。経験に基づいて、分析できる要件は次のとおりです。
1)ページが編集状態にある場合、つまり、画像リストが空でない限り、データベースからQueryされた状態は、最初に画像を表示する必要があります。また、Uploadボタンが見つかった画像リストの長さとアップロード制限に従って表示されるかどうかを制御する必要があります。
2)現在のページが表示されるが変更されていない状態である場合、アップロードボタンと削除ボタンを初期段階で削除する必要があります。
要件分析が完了したら、実装のアイデアを説明させてください。
2。実装のアイデア
これはフォームページであるため、画像をアップロードした後に背景に送信する場合は、テキストフィールドが必要です。それで、私が静的ページをやっていたとき、私はこのテキストフィールドを考慮に入れました。新しい画像をアップロードして画像を削除した後、このテキストフィールドの値を変更する必要がありました。静的ページが作成されたときのこの部分の構造は次のとおりです。
<div> <label>法人IDカードの電子バージョン</label> <div> <input id = "legalpersonidpic-input" name = "legalpersonidpic" type = "hidden"> <ul id = "legalpersonidpic-view"> <li> <a href = "javascript:;">+</a> < href = "#"> <i> </i>例を表示</a> </p> </div> </div>
この構造から、アップロード領域全体を1つのULに配置し、最初のUL LIをアップロードボタンとして使用することもわかります。この機能を完了するために、主なタスクは、コールバックのアップロードとアップロード、画像プレビューの追加または削除、およびテキストフィールド値の管理です。この観点からは、責任の分離のアイデアと組み合わされて、この関数には少なくとも3つのコンポーネントが必要です。1つはファイルアップロードを担当し、1つは画像プレビュー管理の責任があり、もう1つはテキストドメイン値管理を担当します。これらの3つの機能をペアまたはすべてでカプセル化しないでください。その場合、機能的な結合が強すぎ、記述されたコンポーネントは拡張可能で再利用可能です。これら3つのコンポーネント間で相互作用が必要な場合は、コールバック関数またはパブリッシュサブスクライブモードの助けを借りて、それらを外部から呼ばれるインターフェイスに定義するだけです。
ただし、テキストドメイン値の管理は非常に単純であり、コンポーネントとして書かれているかどうかは関係ありませんが、少なくとも関数レベルのカプセル化が必要です。ファイルアップロードコンポーネントはこの記事の焦点ではありませんが、インターネット上には、直接使用するか二次カプセル化を使用するかどうかにかかわらず、Webuploaderなど、インターネット上に多くの既製のオープンソースプラグインがあります。画像プレビューの関数は、この記事のコアコンテンツです。 ImageUploAdviewコンポーネントは、そのカプセル化です。要件の観点から、このコンポーネントには3つのセマンティックサンプルメソッド、つまりレンダリング、追加、および削除のみがあります。レンダリングは、初期化が完了した後に初期プレビューリストを表示するために使用され、付録はアップロード後に新しい画像プレビューを追加するために使用され、既存の画像プレビューを削除するためにDelitemが使用されます。この基本的なアイデアによれば、コンポーネント開発の要件と経験に基づいて、オプションとイベントを設計するだけです。
以前の要件から、このImageUploAdviewコンポーネントのレンダリングがページステータスの影響を受けることがわかりました。ページが表示されている場合、このコンポーネントはアップロードして削除できないため、読み取りオプションを追加することを検討できます。同時に、そのアップロード操作と削除操作は、アップロード制限に関連するUIロジックのアップロードボタンにも影響します。柔軟性のために、アップロード制限もオプションと見なす必要があります。前の段落で述べた3つのインスタンスメソッドから、イベントの定義に関する以前の経験によると、インスタンスメソッドは一般に、ブートストラップのプラグインのようにイベントのペアを定義します。たとえば、レンダリングメソッドはレンダリングを定義できます。このイベントは、レンダリングの主なロジックが実行される前にトリガーされます。外部リスナーがこのイベントのPreventDefault()メソッドを呼び出す場合、レンダリングの主なロジックは実行されません。レンダリング後のイベントもあります。これは、レンダリングの主なロジックが実行された後にトリガーされます。このペアワイズ定義イベントの利点は、コンポーネント機能を拡張するための外部メソッドを提供するだけでなく、コンポーネントのデフォルト動作の管理を増加させることです。
最後に、以前の仕事の経験から、プレビューのための写真のアップロードに加えて、ビデオのアップロード、オーディオのアップロード、通常のドキュメントのアップロードなども行ったので、今回この機能に遭遇したとき、これらの機能を基本クラス、画像アップロード、ビデオのアップロードなどから抽出する必要があると感じました。この基本クラスのもう1つの利点は、一般的なロジックをHTML構造から完全に分離できることです。この基本クラスでは、一般的なイベントのリスニングとトリガーだけでなく、オプションやコンポーネントの動作の定義やコンポーネントの動作の定義(レンダリング、追加、デリテム)など、一般的なことのみが行われます。サブクラスが実装するために固定インターフェイスを残す必要があります。その後の実装では、この基本クラスの関数を完了するためにFileuploadbaseviewコンポーネントを定義しました。この基本クラスには、HTMLまたはCSS処理のロジックは含まれていません。完了したい関数を抽象化し、ビジネスロジックを処理しません。ビジネスロジックに従って実装されたサブクラスは、HTML構造によって制限されるため、サブクラスの適用範囲は小さいです。また、基本クラスはHTML構造から完全に分離されているため、アプリケーションの範囲が大きくなります。
3。実装の詳細
パート2の実装アイデアから、実装されるクラスは次のとおりです。FileuploadBaseViewとImageUploadview、前者は後者の基本クラスです。同時に、コンポーネントがイベント管理機能を提供する必要があることを考慮すると、以前のブログでeventbase.jsを使用する必要があり、FileuploadBaseViewはライブラリのイベントベースコンポーネントを継承する必要があります。クラスの定義と継承があることを考慮すると、コンポーネントとコンポーネントの継承関係を定義するために、前に書かれた継承ライブラリclass.jsも使用する必要があります。関連コンポーネントの継承関係は次のとおりです。imageuploadview拡張fileuploadbaseview拡張イベントベース。
(注:次の関連コードは、モジュール性でSEAJを使用しています。)
fileuploadbaseviewが行うことは次のとおりです。
1)一般的なオプションと一般的なイベント管理を定義します
このコンポーネントのデフォルト構成では、すべての一般的なオプションと一般的なイベントの定義を確認できます。
var defaults = {data:[]、//表示されるデータのリストは、[{url: 'xxx.png'}、{url: 'yyyy.png'}] sizelimit:0、// baseviewで表示される要素の数を制限するために、base in controlを制限することを制限することを制限するために、[yyyy.png '}] sizelimit:0、//などのオブジェクトタイプである必要があります。削除onbeforerender:$ .noop、//forereport.beforereport、event、トリガーonrender:$ .noop、//forereport.after after event after renderメソッドが呼び出される前、$ .noop、// append.nop、trigger onappered:noop、append.appter onebed onebed、trigger enpered、$ .noop、trigger // delitem.before eventに遵守すると、ondelitem:$ .noopがdelitemメソッドが呼び出される前に$ .noopがdelitem.after eventを順守し、トリガー};コンポーネントのinitメソッドでは、一般的なオプションとイベント管理の初期化ロジックを確認できます。
init:function(element、options){// this.base; // instance属性var opts = this.options = this.getoptions(options); this.data = resolvedata(opts.data); opts.dataを削除します。 this.sizelimit = opts.sizelimit; this.readonly = opts.readonly; //バインディングイベントthis.on( 'render.before'、$ .proxy(opts.onbeforerender、this)); this.on( 'render.after'、$ .proxy(opts.onrender、this)); this.on( 'append.before'、$ .proxy(opts.onbeforeappend、this)); this.on( 'append.after'、$ .proxy(opts.onappend、this)); this.on( 'delitem.before'、$ .proxy(opts.onbeforedelitem、this)); this.on( 'delitem.after'、$ .proxy(opts.ondelitem、this));}、2)サブクラスによって実装できるコンポーネントと予備のインターフェイスの動作を定義します。
render:function(){/*** renderはテンプレートです。サブクラスはレンダリングメソッドをオーバーライドする必要はありません。_renderメソッド*をオーバーライドするだけで済む必要があります。サブクラスのレンダリングメソッドが呼び出された場合、親クラスのレンダリング方法は_renderメソッドを実行する場合、_レンダーメソッドの_レンダーメソッドが呼び出されます。 this.trigger(e = $ .event( 'render.before')); if(e.isdefaultPrevented())return; this._render(); this.trigger($。event( 'render.after'));}、// subclasses _render method_render:function(){}、append:function(item e; if(!item)return; item = resolvedataitem(item); the.trigger(e = $ .event( 'append.before')、 'appent.before')、 'appent.bethed(e.thed) return; this.data.push(item); this._append(item); this.trigger($。event( 'append.after')、item);}、// subclasses _append methoded:function(data){}、delitem:function(uuid){var e、thisegetaitem(uuid); return; this.trigger(e = $ .event( 'delitem.before')、item); if(e.isdefaultprevented())return; this.data.splice(this.getDataiteMindex(uuid)、1); this._delitem(item); this.trigger($。 _delitem method_delitem:function(data){}動作の前後にイベント配布ロジックを均一に処理するために、レンダリング、append、delitemの主なロジックは、サブクラスによって実装する必要がある方法_render、_append、_delitemに抽出されます。サブクラスのレンダリング方法が呼び出されると、親クラスの方法が実際に呼び出されますが、親クラスが_renderメソッドを実行すると、サブクラスの方法が実行され、他の2つの方法も類似しています。サブクラスは、3つのメソッドのレンダリング、追加、および削除をオーバーライドできないことに注意してください。そうしないと、関連するイベントのトリガーロジックを自分で処理する必要があります。
FileuploadbaseViewの全体的な実装は次のとおりです。
define(function(require、exports、module){var $ = require( 'jquery'); var class = require( 'mod/class'); var eventbase = require( 'mod/eventbase'); var defaults = {data:[]、//データのリストを表示するには、リスト要素はオブジェクトタイプのものでなければなりません。 'yyy.png'}] sizelimit:0、// baseviewに表示される要素の数を制限するには、0が制限がないことを意味します。 onbeforepend:$ .noop、//対応するappend.befory event、トリガーonappend:$ .noop、//対応するappend.noop、$ .noop、//対応するappent.appent.appent. onbeforedelitem:$ .noop、// compansed.apter onbeforedem:$ .nup、triggeritem:$ .noop、trigger delitem.befter event、trigger ondelitem:$ .noop //対応するdeletem.after event、trigger};/***データ処理、_uuid属性をデータの各レコードに追加して検索を促進するために_uuid属性を追加して、resolvedata(data){var time = new Date(); gettime(); map(d)時間);});} function ResolvedAtaitem(data、time){time = time ||。 base. //インスタンス属性= this.data = resolvedata(opts.data); $ .proxy(opts.onbeforerender、 'render.after'(opts.onrender、this)); this.on( 'delitem.before'、$ .proxy(opts.onbeforedelitem、this)); defaults;}、getDataitem:function(uuid){// get dateItemreturn this.data.filter(function(item){return item._uuid === uuid;})[0];}、getDataiteMindex:function(uuid){var ret; this.data.foreeach(function(uuid) (ret = i);}); rett;}、render:function(){/*** renderはテンプレートです。_renderメソッドをオーバーライドする必要はありません。イベントの前後の操作。 {var e; if(!item)return; item = resolvedataitem(item); this.trigger(e = $ .event( 'append.before')、item); if(e.isdefaultPrevented())return; this.data.push(item); this._append(item); this.trigger($。 _append method_append:function(data){}、delitem:function(uuid){var e、item = this.getdataitem(uuid); if(!item)return; this.trigger(e = $ .event( 'delitem.before')、item); if(e.isdefaultprevented()) return; this.data.splice(this.getDataiteMindex(uuid)、1); this._delitem(item); this.trigger($ defaults}}); return fileuploadbaseview;});ImageUploAdviewの実装は比較的単純で、ブランクを埋めるのと同様です。説明する点がいくつかあります:
1)このクラスのデフォルトは、親クラスのデフォルトを拡張して、このサブクラスのデフォルトオプションを追加し、親クラスのデフォルトオプションの定義を保持する必要があります。静的ページ構造によると、OnappendClickイベントが追加されており、このイベントでは、ファイルアップロードコンポーネントの関連する方法を外部的に呼び出すことができます。
//親クラスのデフォルトのdefaultSvarを継承して拡張しますdefaults = $ .extend({}、fileuploadbaseview.defaults、{onappendclick:$ .noop //アップロードボタンをクリックするとコールバック});2)initメソッドでは、それらの一般的な論理処理を完了するために、親クラスのinitメソッドを呼び出す必要があります。 initの終わりに、コンポーネントがインスタンス化された後に効果を確認できるように、レンダリング方法を手動で呼び出す必要があります。
その他の実装は、純粋にビジネスロジックの実装であり、パート2の要件に密接に関連しています。
ImageUploAdviewの全体的な実装は次のとおりです。
define(function(require、exports、module){var $ = require( 'jquery'); var class = require( 'mod/class'); var fileuploadbaseview = require( 'mod/fileuploadbaseview'); // default defaultsvar defaults = $ .extend({}、fileuploadbaseviewied({}、fileuploadbaseviewied) $ .noop //アップロードボタンをクリックしたときのコールバック}); var imageuploadview = class({instancemembers:{init:function(element、options){var $ element = this。$(element); var opts = this.getoptions(options); Options); //リスナーを追加して削除し、処理を削除し、if(!this.readonly){var this = this; that.on( 'appendclick'、$ .proxy(opts.onappendclick、this)); $ element.on( 'click.append'、 '.view-act-add'、function(e){e.preventdefault(); that.trigger( 'appendclick');}); $ element.on( 'click.remove'、 '.view-act-del'、function(e){var $ this = $(e.currenttarget); this.data($ this.data( 'uuid')); e.preventdefault( {return defaults;}、_ setItemaddhtml:function(){this。$ element.prend( '<li> <a href = "javascript:;">+</a> </li>');}、_ clearitemaddhtml:function($ itemaddli){$ itemaddli(); {var html = []、that = this; //それは読み取り専用の状態ではなく、アップロード制限に達していない場合、アップロードボタンを追加します。 {html.push(that._getitemrenderhtml(item))}); this。$ element.append($(html.join( ''));}、_ getItemrenderhtml:function(item){return ['<li id = "'、item._uid、 '> <a href = src = "'、item.url、'"> '、this.readonly?' <span data-uuid = "'、item._uuid、'"> delete </span> '、' </a> </li> ']。 this. $ element.find( 'li.view-item-add'); //アップロード制限に到達した場合、アップロードボタンを削除します(this.sizelimit && this.sizelimit <= this.data.length && $ itemaddli.length){this._clearitemaddhtml(! {this._setItemaddhtml();}}、_ append:function(data){this。$ element.append($(this._getitemrenderhtml(data))); this._dealwithsizelimit(}、_ delitem:function(data){$( '#' + data._uuid).remove(); this._dealwithsizelimit();}}、extend:fileuploadbaseview});4。デモの指示
デモプロジェクト構造は次のとおりです。
フレーム化されているのは、デモンストレーションのコアコードです。その中で、Fileuploadbaserview.jsとImageuploadview.jsは、以前の実装で実装された2つのコアコンポーネントです。 fileuploader.jsは、アップロードコンポーネントをシミュレートするために使用されます。そのインスタンスには、上向きのコールバックがあり、アップロードが成功していることを示しています。また、選択ファイルウィンドウを開いてアップロードするプロセスをシミュレートするために使用されるOpenChooseFilewinもあります。
定義(function(require、exports、module){return function(){var imglist = ['../img/1.jpg'../img/2.jpg'、'../img/3.jpg','../img/4.jpg']、i = 0; function(){setimeout(function(){that.onsuccess(imglist [i ++]); if(i == imglist.length){i = 0;}}、1000);}}});App/Regist.jsはデモンストレーションページの論理コードであり、重要な部分はコメントで説明されています。
define(function(require、exports、module){var $ = require( 'jquery'); var imageuploadview = require( 'mod/imageuploadview'); var fileuploader = require( 'mod/fileuploader');アップロードコンポーネントが正常にアップロードされ、Imageuploadviewコンポーネントが特定のアイテムを削除した後、$ legalsenidpic var $ legalsersidpic = $( '#legalseridpic-input')、data = json.parse($ legalsenidpic.val()|| '); Imageuploadviewコンポーネント//ファイルアップロードが正常にアップロードされた後、新しくアップロードされたファイルを$ LegalPersonIDPIC // $ legalPersonIdpic Stores var appendimageInputValue = function($ input、item){var value = json.put.val()|| '[]'); value.push(item); $ input.val(json.stringify(value));}; // $ legalpersonidpicの保存された情報を削除するために、var var value = json.parsed.bal() index; value.foreach(function(item、i){if(item._uuid === uuid){index = i;}}); value.splice(index、1); $ input.val(json.stringify(value));}; var fileuploader = new fileuploader() {url:uploadValue}; LegalPersonIdpicView.Append(item); appensimageInputValue($ legalpersonIdpic、item);}; var legalpersonidpicview = new Imageuploadview( '#LegalPersonIdpic-view'、{データ:データ、sizelimit: fileuploader.openchoosefilewin();}、ondelitem:function(data){remaimageInputValue($ legalPersonIdpic、data._uuid);}});});5。この記事の概要
ImageUploAdviewコンポーネントは最終的に実装するのは難しくありませんが、私はそれや他の親クラスについて考えるのに多くの時間を費やしてそれを実装しました。この記事で表現されているプログラミングのアイデアのこれらの2つの側面に関する見解は、私自身の個人的な経験にすぎません。抽象的なレベルのため、誰もが考えている方法と最終的な理解は同じではありません。したがって、私は自分が正しいか間違っているかを直接言うことはできません。執筆の目的は、共有してコミュニケーションをとることであり、この点で彼らのアイデアについてあなたに話すことをいとわない他の経験豊富な友人がいるかどうかを確認することです。誰もが他の人のアイデアについてあまりにも多くを読んだ後、彼らは彼ら自身のプログラミングのアイデアトレーニングを助けると信じています。