تقدم هذه المقالة فكرة التنفيذ للصور المشتركة على صفحة الويب لإنشاء معاينات صور صغيرة مباشرة على الصفحة بعد تحميلها. بالنظر إلى أن هذه الوظيفة لها قابلية للتطبيق ، يتم تغليف المنطق ذي الصلة في مكون ImageUploadview. يمكن استخدام تأثير الاستخدام الفعلي لعرض عروض GIT في الفقرة التالية. في عملية تنفيذ هذا المكون ، نستخدم المحتوى ذي الصلة المقدمة في المدونات السابقة ، مثل Class.js Library Class.js ، ومكتبة إدارة الأحداث eventbase.js من أي مكون ، والذي يتضمن أيضًا بعض الأفكار حول فصل المسؤوليات ، وفصل الأداء والسلوك. مرحبًا بك في القراءة والتواصل.
تأثير التوضيح:
ملاحظة: نظرًا لأن رموز العرض التوضيحي كلها ثابتة ، يتم محاكاة المكون الذي تم تحميله بواسطة الملف بواسطة SetTimeOut ، ولكن طريقة الاتصال الخاصة بها هي نفسها تمامًا كما أستخدم مكون التحميل في عملي الفعلي ، وبالتالي فإن تنفيذ التعليمات البرمجية لتأثير العرض التوضيحي يتماشى تمامًا مع المتطلبات الوظيفية الحقيقية.
وفقًا لأفكار مدونتي السابقة ، دعنا نقدم أولاً متطلبات وظيفة معاينة التحميل هذه.
1. تحليل المتطلبات
وفقًا لتقديم العرض التوضيحي السابق ، تكون متطلبات التحليل كما يلي:
1) في منطقة التحميل الأولية ، يتم عرض زر تحميل واحد فقط قابلة للنقر. عند النقر فوق هذا الزر ، سيتم عرض الصورة التي تم تحميلها في منطقة المعاينة اللاحقة.
2) بعد إضافة الصورة التي تم تحميلها إلى منطقة المعاينة ، يمكنك إزالتها عن طريق حذف الزر.
3) عندما يصل العدد الإجمالي للصور التي تم تحميلها إلى حد معين ، على سبيل المثال ، فإن حد التحميل في العرض التوضيحي هو 4 ، قم بإزالة زر التحميل ؛
4) عندما يصل إجمالي عدد الصور التي تم تحميلها إلى حد معين ، إذا تمت إزالة صورة معينة من خلال عملية الحذف ، فيجب عرض زر التحميل.
المتطلبات أعلاه مرئية. بناءً على الخبرة ، فإن المتطلبات التي يمكن تحليلها هي على النحو التالي:
1) إذا كانت الصفحة في حالة التحرير ، أي أن الحالة قد استفسرت من قاعدة البيانات ، طالما أن قائمة الصور ليست فارغة ، يجب عرض الصورة في البداية ؛ ويجب أيضًا التحكم في ما إذا كان زر التحميل يتم عرضه وفقًا لطول قائمة الصور التي تم العثور عليها وحد التحميل ؛
2) إذا كانت الصفحة الحالية هي حالة لا يمكن عرضها إلا ولكن لم يتم تغييرها ، فيجب إزالة زر التحميل وزر الحذف في المرحلة الأولية.
بعد اكتمال تحليل المتطلبات ، اسمحوا لي أن أشرح أفكار التنفيذ الخاصة بي.
2. أفكار التنفيذ
نظرًا لأن هذه صفحة نموذج ، إذا كنت ترغب في إرسالها إلى الخلفية بعد تحميل الصورة ، يجب أن تحتاج إلى حقل نص. لذلك عندما كنت أقوم بصفحة ثابتة ، أخذت حقل النص هذا في الاعتبار. بعد تحميل صورة جديدة وحذف الصورة ، اضطررت إلى تعديل قيمة حقل النص هذا. بنية هذا الجزء عندما تم صنع صفحات ثابتة على النحو التالي:
<viv> <label> الإصدار الإلكتروني من بطاقة معرف الشخص القانوني </label> <viv> <input id = "legalpersonidpic-input" name = "LegalPersonIdpic" type = "hidden"> <ul id = "LegalPersonIdpic-view"> <li> HREF = "#"> <i> </i> عرض مثال </a> </p> </viv> </viv>
من هذا الهيكل ، يمكننا أيضًا أن نرى أنني أضع منطقة التحميل بأكملها في UL واحدة ، ثم استخدم أول LI كزر التحميل. من أجل إكمال هذه الوظيفة ، فإن مهامنا الرئيسية هي: تحميل وتحميل عمليات الاسترجاعات ، وإضافة أو حذف معاينات الصور ، وإدارة قيم حقل النص. من وجهة النظر هذه ، إلى جانب فكرة الفصل بين المسؤوليات ، تتطلب هذه الوظيفة ثلاثة مكونات على الأقل ، واحدة مسؤولة عن تحميل الملفات ، والمسؤولة عن إدارة معاينة الصور ، والآخر المسؤول عن إدارة قيم المجال النصية. لا تغلف أبدًا هذه الوظائف الثلاث في أزواج أو جميعًا معًا. في هذه الحالة ، يكون الاقتران الوظيفي قويًا جدًا والمكونات المكتوبة قابلة للتمديد وقابلة لإعادة الاستخدام. إذا كان التفاعل مطلوبًا بين هذه المكونات الثلاثة ، فنحن بحاجة فقط إلى تحديدها إلى واجهات تسمى خارجيًا بمساعدة وظائف رد الاتصال أو وضع النشر.
ومع ذلك ، فإن إدارة قيم مجال النص بسيطة للغاية ، ولا يهم ما إذا كانت مكتوبة كمكون أم لا ، ولكن على الأقل مطلوب تغليف على مستوى الوظيفة. على الرغم من أن مكون تحميل الملف ليس محور هذه المقالة ، إلا أن هناك العديد من المكونات الإضافية مفتوحة المصدر جاهزة على الإنترنت ، مثل WebUploader ، والتي يمكن تطبيقها سواء تم استخدامها مباشرة أو ثانوية. وظيفة معاينة الصورة هي المحتوى الأساسي لهذه المقالة. مكون ImageUploadview هو تغليفه. من وجهة نظر المتطلبات ، لا يوجد سوى ثلاث طرق مثال دلالي لهذا المكون ، وهي تقديم وإلحاق و SeliTem. يتم استخدام العرض لعرض قائمة المعاينة الأولية بعد اكتمال التهيئة ، ويتم استخدام إلحاق لإضافة معاينة جديدة للصور بعد التحميل ، ويتم استخدام DeliTem لحذف معاينات الصور الموجودة. وفقًا لهذه الفكرة الأساسية ، نحتاج فقط إلى تصميم الخيارات والأحداث لها بناءً على المتطلبات والخبرة في تطوير المكونات.
من المتطلبات السابقة ، وجدنا أن تقديم مكون ImageUploadview هذا سيتأثر بحالة الصفحة. عندما تكون الصفحة في وضع العرض ، لا يمكن تحميل هذا المكون وحذفه ، بحيث يمكنك التفكير في إضافة خيار قراءة إليه. في الوقت نفسه ، ستؤثر عمليات التحميل والحذف أيضًا على منطق واجهة المستخدم لزر التحميل ، والذي يرتبط بحد التحميل. من أجل المرونة ، يجب أيضًا اعتبار حد التحميل خيارًا. من بين أساليب المثيل الثلاثة المذكورة في الفقرة السابقة ، وفقًا لتجربتك السابقة في تحديد الأحداث ، تحدد طريقة المثيل عمومًا زوجًا من الأحداث ، تمامًا مثل المكون الإضافي من bootstrap. على سبيل المثال ، يمكن أن تحدد طريقة التجسيد. يتم تشغيل هذا الحدث قبل تنفيذ المنطق الرئيسي للعرض. إذا استدعى المستمع الخارجي طريقة PreventDefault () لهذا الحدث ، فلن يتم تنفيذ المنطق الرئيسي للعرض ؛ هناك أيضًا حدث Render.after ، والذي يتم تشغيله بعد تنفيذ المنطق الرئيسي للعرض. تتمثل ميزة حدث التعريف الزوجي هذا في أنه لا يوفر طرقًا خارجية لتوسيع وظائف المكون فحسب ، بل يزيد أيضًا من إدارة السلوك الافتراضي للمكون.
أخيرًا ، من تجربتي السابقة ، بالإضافة إلى تحميل الصور للمعاينة ، قمت أيضًا بتحميل مقاطع الفيديو ، وتحميل الصوت ، وتحميل المستندات العادية ، وما إلى ذلك ، لذلك عندما واجهت هذه الوظيفة هذه المرة ، شعرت أنه يجب علي استخراج أشياء مماثلة من هذه الوظائف كطبيلة أساسية ، وتحميل الصور ، وتحميل الفيديو ، وما إلى ذلك ، على التوالي من الفئة الأساسية لتنفيذ هذه الوظائف. ميزة أخرى من هذه الفئة الأساسية هي أنه يمكنه فصل المنطق العام تمامًا عن بنية HTML. في هذه الفئة الأساسية ، تتم فقط الأشياء الشائعة ، مثل تعريف الخيارات وسلوك المكون (العرض ، إلحاق ، DeliTem) ، وكذلك الاستماع والتشغيل للأحداث العامة. يحتاج فقط إلى ترك واجهة ثابتة لتنفيذ الفئة الفرعية. في التنفيذ اللاحق ، حددت مكون FileUploadBaseView لإكمال وظائف هذه الفئة الأساسية. لا تحتوي هذه الفئة الأساسية على أي منطق لمعالجة HTML أو CSS. إنه مجرد تجريد الوظائف التي نريد إكمالها ولا تتعامل مع أي منطق عمل. ستقتصر الفئات الفرعية التي تم تنفيذها وفقًا لمنطق الأعمال على هيكل HTML ، وبالتالي فإن نطاق تطبيق الفئات الفرعية صغيرة ؛ ولأن الفئة الأساسية مفصولة تمامًا عن بنية HTML ، فإن لديها نطاقًا أكبر من التطبيق.
3. تفاصيل التنفيذ
من فكرة التنفيذ للجزء 2 ، فإن الفئات التي سيتم تنفيذها هي: FileUploadBaseView و ImageUploadview ، الأول هو الفئة الأساسية للأخير. في الوقت نفسه ، بالنظر إلى أن المكون يحتاج إلى توفير وظائف لإدارة الأحداث ، نحتاج إلى استخدام eventbase.js في المدونة السابقة ، ويجب أن يرث FileUploadBaseView مكون قاعدة الحدث للمكتبة ؛ بالنظر إلى وجود تعريف فئة وميراث ، نحتاج أيضًا إلى استخدام Class.js مكتبة الميراث من قبل لتحديد المكون وعلاقة الميراث للمكون. علاقة الميراث للمكونات ذات الصلة هي: ImageUploadview تمديد FileUploadBaseView تمديد الحدث.
(ملاحظة: يستخدم الرمز التالي التالي Seajs في النموذج.)
ما يفعله FileUploadBaseView هو:
1) تحديد الخيارات الشائعة وإدارة الأحداث المشتركة
في تكوين هذا المكون الافتراضي ، يمكنك رؤية تعريفات جميع الخيارات الشائعة والأحداث الشائعة:
var defaults = {data: [] ، // يجب أن تكون قائمة البيانات المراد عرضها من نوع الكائن ، مثل [{url: 'xxx.png'} ، {url: 'yyyy.png'}] الإضافة والحذف onbeforerender: $ .noop ، //forereport.be fore event ، trigger onrender: $ .noop ، //forereport.after قبل أن يتم استدعاء طريقة العرض ، و onBeforeAppend: $ .nOP ، // امتثالا للتسجيل. $ .noop ، // امتثالا لحدث deliTem.before ، الزناد ondelitem: $ .noop قبل أن تسمى طريقة deliTem // الامتثال لحدث deliTem.after ، المشغى} ؛في طريقة init للمكون ، يمكنك رؤية منطق التهيئة للخيار العام وإدارة الأحداث:
init: function (element ، reports) {// استدعاء طريقة init في event event event class من خلال هذا. this.data = solvedata (opts.data) ؛ حذف opts.data ؛ this.sizelimit = opts.sizelimit ؛ this.readonly = opts.readonly ؛ // entering event 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 ، تسمى طريقة _render للفئة الفرعية* وهذا سوف يوحد عمليات التشغيل من قبل وبعد الأحداث* ؛ this.trigger (e = $ .event ('render.before')) ؛ if (e.isDefaultPrevented ()) return ؛ this._render () ؛ this.trigger ($. event ('render.after'))) ؛} ، // الفئات الفرعية تحتاج إلى تنفيذ _render method_render: function () {} ، إلحاق: وظيفة (عنصر) {var e (e.isDefaultPrevented ()) return ؛ this.data.push (item) ؛ this._append (item) ؛ this.trigger ($. event ('append.after') ، item) ؛} ،. this.getDataItem (uuid) ؛ if (! العنصر) إرجاع ؛ this.trigger (e = $ .event ('delitem.before') ، item) ؛ if (e.isDefaultPrevented ()) 1) ؛ this._delitem (item) ؛ this.trigger ($. event ('delitem.after') ، item) ؛} ،من أجل التعامل بشكل موحد لمنطق توزيع الأحداث قبل وبعد السلوك ، يتم استخراج المنطق الرئيسي للعرض ، التذييل ، DeliTem إلى طرق _render ، _append و _delitem التي تحتاج إلى تنفيذها بواسطة الفئات الفرعية. عندما يتم استدعاء طريقة تقديم الفئة الفرعية ، يتم استدعاء طريقة الفئة الأصل فعليًا ، ولكن عندما تنفذ الفئة الأصل طريقة _render ، يتم تنفيذ طريقة الفئة الفرعية ، والطريقتين الأخريين متشابهة أيضًا. تجدر الإشارة إلى أن الفئات الفرعية لا يمكن أن تتجاوز الأساليب الثلاثة التي تقدمها وإلحاقها وحذفها ، وإلا عليك التعامل مع منطق الزناد للأحداث ذات الصلة بنفسك.
التنفيذ العام لـ FileUploadBaseView هو كما يلي:
define (function (require ، orports ، module) {var $ = require ('jQuery') ؛ var class = require ('mod/class') ؛ var eventbase = required ('mod/eventbase') ؛ var defaults = {data: [] 'yyyy.png'}] sizelimit: 0 ، // للحد من عدد العناصر المعروضة في baseview ، إذا كان 0 يعني عدم وجود حد readonly: false ، // للتحكم onbeforeappend: $ .noop ، // apperting espend.be fore event ، trigger onappend: $ .noop ، // apporting. // المقابل DeliTem.be Fore Event ، Trigger onDeleTem: $ .noop // المقابلة DeliTem.after حدث ، trigger} ؛/*** معالجة البيانات ، إضافة سمة _uuid إلى كل سجل من البيانات لتسهيل البحث*/وظيفة resolvedata (data) {var time = new time (). resolvedataitem (d ، time) ؛}) ؛} الدالة resolvedataitem (البيانات ، الوقت) {time || date () {// استدعاء طريقة event events من خلال هذا. this.on (redust.before "، $ .proxy (Opts.Onbeorerender ،) ؛ $ .proxy (opts.onappend ، هذا) ؛ this.getDefaults () ، الخيارات) ؛} ، getDefaults: function () {return defaults ؛} ، getDataitem: function (uuid) {// get dateItemReturn this.data.filter (function (item) {return item._uuid === uuid ؛}) [0] ret ؛ this.data.foreach (البند ، i) {item._uuid === UUID && (ret = i) ؛}) يتم تنفيذ طريقة _render من الفئة الفرعية* تحتاج إلى تنفيذ _render method_render: function () {} ، إلحاق: الدالة (العنصر) {var e ؛ if (! item) return ؛ item = solvedataitem (item) ؛ this.trigger (e = $. return ؛ this.data.push (item) ؛ this._append (item) ؛ this.trigger ($. event ('append. after') ، item) ؛} ، return ؛ this.trigger (e = $ .event ('deliTem.before') ، item) ؛ if (e.isDefaultPrevented ()) _delitem method_delitem: function (data) {}} ، تمديد: eventbase ، staticmembers: {defaults: defaults}}) ؛ إرجاع fileuploadbaseview ؛}) ؛تطبيق ImageUploadview بسيط نسبيًا ، على غرار ملء الفراغات. هناك بضع نقاط لشرح:
1) تحتاج الإعدادات الافتراضية لهذه الفئة إلى تمديد الافتراضات لفئة الأصل لإضافة الخيارات الافتراضية لهذه الفئة الفرعية ، وكذلك الاحتفاظ بتعريف الخيارات الافتراضية للفئة الأصل ؛ وفقًا لهيكل الصفحة الثابتة ، تمت إضافة حدث onappendclick ، ويمكن استدعاء الطرق ذات الصلة لمكونات تحميل الملفات خارجيًا في هذا الحدث:
// وراثة وتوسيع الافتراض الافتراضي الافتراضي من الفئة الأم الافتراضية = $ .extend ({} ، fileUploadBaseView.defaults ، {onappendclick: $ .noop // callback عند النقر فوق زر التحميل}) ؛2) في طريقة init ، يجب استدعاء طريقة init للفئة الأصل لإكمال تلك المعالجة المنطقية العامة ؛ في نهاية init ، يجب عليك استدعاء طريقة العرض يدويًا حتى تتمكن من رؤية التأثير بعد إنشاء مثيل للمكون:
التطبيقات الأخرى هي تطبيقات منطق الأعمال البحتة وترتبط ارتباطًا وثيقًا بمتطلبات الجزء 2.
التنفيذ العام لـ ImageUploadview هو كما يلي:
define (function (require ، orports ، module) {var $ = require ('jQuery') ؛ var class = require ('mod/class') ؛ var fileuploadbaseview = require ('mod/fileuploadbaseview') {onappendclick: $ .noop // callback عند النقر فوق زر التحميل}) ؛ var imagePloadview = class ({instancemembers: {init: function (element ، reports) {var $ element = this. $ element = $ (element) ؛ var opts = this.getOptions (Options) ؛ this.base (هذا العنصر $ ، الخيارات) ؛ // أضف التحميل وحذف المستمعين وحذف المعالجة إذا (! this.readonly) {var that = this ؛ that.on ('appendclick' ، $ .proxy (opts.onappendclick ، this) ؛ $ element.on ('click.append' ، '. that.trigger ('appendclick') ؛}) ؛ $ element.on ('click.remove' ، '.view-act-del' ، function (e) {var $ this = $ ( () {return defaults ؛} ، _ setitemaddhtml: function () {this. $ element.prepend ($ ('<li> <a href = "javaScript: ؛ function () {var html = [] ، that = this ؛ // إذا لم تكن حالة القراءة فقط ولم تصل إلى حد التحميل ، أضف زر التحميل إذا (! (this.readonly || (this.sizelimit && this.sizelimit <= this.data.length))) (عنصر) {html.push (that._getitemrenderhtml (item))}) ؛ هذا. $ element.append ($ (html.join ('' '))) ؛} ، _ getItemRenderHtml: function (item) {return [' <li id = "'، item._uuid ،' ' src = "'، item.url ،'"> '، this.readonly؟ هذا. $ element.find ('li.view-item-add') ؛ // إذا تم الوصول إلى حد التحميل ، فقم بإزالة زر التحميل إذا (this.sizelimit && this.sizelimit <= this.data.length && $ itemaddli.length) (! $ itemaddli.length) {this._setItemAddhtml () ؛ data._uuid) .remove ()4. التعليمات التجريبية
هيكل المشروع التجريبي هو:
ما هو مؤطر هو الكود الأساسي للظهور. من بينها ، FileUploAdbaserview.js و ImageUploadview.js هما المكونان الأساسيان المنفذان في التنفيذ السابق. يتم استخدام FileUploader.js لمحاكاة مكونات التحميل. مثيلها له رد اتصال onsccess ، مما يشير إلى أن التحميل ناجح ؛ يوجد أيضًا OpenChooseFileWin لمحاكاة عملية فتح نافذة ملف التحديد وتحميلها:
define (function (require ، exports ، module) {return function () {var imglist = ['../img/1.jpg' ،،'../img/2.jpg' ،''../img/3.jpg' ،'../img/4.jpg'] function () {setTimeOut (function () {that.onsuccess (imglist [i ++]) ؛ if (i == imglist.length) {i = 0 ؛}} ، 1000) ؛}}}) ؛App/Regist.js هو الكود المنطقي لصفحة العرض التوضيحي ، وتم شرح الأجزاء الرئيسية مع التعليقات:
define (function (require ، orports ، module) {var $ = require ('jQuery') ؛ var imageUploadview = require ('mod/imageUploadview') ؛ var fileuploader = require ('mod/fileuploader') ؛ يتم تحميل المكون بنجاح وبعد حذف مكون ImageUploadview عنصرًا معينًا ، سيؤثر على قيمة $ LegalPersonIdpic var $ LegalPersonIdpic = $ ('#LegalPersonIdpic') ImageUploadview component // بعد تحميل الملف بنجاح ، احفظ الملف الذي تم تحميله حديثًا إلى قيمة $ LegalPersonIdpic // $ LegalPersonIdpic Stores var appendImageInputValue = function ($ input ، item) "[]") '[]') ، index ؛ value.foreach (function (item ، i) {if (item._uuid === uuid) {index = i ؛}) ؛ value.splice (index ، 1) ؛ $ input.val (json.StringIfy)) ؛ {var item = {url: eploadValue} ؛ legalPersonIdpicView.append (item) ؛ appendImageInputValue ($ legalpersonidpic ، item) ؛} ؛ var legalpersonidpicview = new imageUploadview ('#legalpersonidpic-view' ، {data: sivelimit: 4 ، fileuploader.openchoosefilewin () ؛} ، onDelitem: function (data) {removeImageInputValue ($ legalpersonidpic ، data._uuid) ؛}}) ؛}) ؛5. ملخص هذا المقال
ليس من الصعب تنفيذ مكون ImagePloadview في النهاية ، لكنني قضيت أيضًا الكثير من الوقت في التفكير في الأمر وغيرها من فئات الوالدين لتنفيذها ، وقضيت معظم الوقت في استخلاص الفصل بين المسؤوليات والفصل السلوكي. وجهات النظر حول هذين الجانبين من أفكار البرمجة المعبر عنها في هذه المقالة ليست سوى تجربتي الشخصية. بسبب المستوى التجريدي ، لن تكون أساليب تفكير الجميع والتفاهم النهائي هي نفسها. لذلك ، لا أستطيع أن أقول بشكل مباشر ما إذا كنت على صواب أو مخطئ. الغرض من الكتابة هو المشاركة والتواصل ، ومعرفة ما إذا كان هناك أصدقاء آخرون من ذوي الخبرة على استعداد لإخبارك عن أفكارهم في هذا الصدد. أعتقد أنه بعد أن قرأ الجميع الكثير عن أفكار الآخرين ، سيساعدون أيضًا في تدريب أفكار البرمجة الخاصة بهم.