القراءة الموصى بها:
قم بتنفيذ ربط بيانات JS ثنائي الاتجاه البسيط للغاية
MVVM هو نموذج تطوير شائع جدًا للواجهة الأمامية على شبكة الإنترنت. يمكن أن يؤدي استخدام MVVM إلى جعل الكود يركز أكثر على التعامل مع منطق الأعمال بدلاً من الاهتمام بعمليات DOM. في الوقت الحالي ، تشمل أطر MVVM الشهيرة Vue و Avalon و React ، إلخ. بدافع الفضول والرغبة في النضال ، كتبت أيضًا أبسط مكتبة MVVM (MVVM.JS) على طول هذا الاتجاه ، مع ما مجموعه أكثر من 2000 سطر من الكود. التسمية واستخدام التعليمات تشبه VUE. هنا سأشارك مبادئ التنفيذ وأفكار تنظيم الكود الخاصة بي.
فرز الأفكار
MVVM هو من الناحية المفاهيمية نمطًا يفصل حقًا طرق العرض عن منطق البيانات ، و ViewModel هو محور النمط بأكمله. لتنفيذ ViewModel ، تحتاج إلى ربط نموذج البيانات (النموذج) و View (View). يمكن ببساطة تلخيص فكرة التنفيذ بأكملها إلى 5 نقاط:
قم بتنفيذ برنامج التحويل البرمجي لمسح تعليمات واستخراج كل عقدة لعنصر ؛
قم بتنفيذ محلل لتحليل الإرشادات الموجودة على العنصر ، والتي يمكنها تحديث نية التعليمات إلى DOM من خلال وظيفة التحديث (قد تكون هناك حاجة إلى وحدة قد تكون مسؤولة على وجه التحديد عن عرض العرض في الوسط). على سبيل المثال ، عند تحليل العقدة <p v-show = "isShow"> </p> ، احصل أولاً على قيمة isShow في النموذج ، ثم قم بتغيير node.style.display وفقًا لـ IsShow للتحكم في شاشة العرض وإخفائه ؛
يمكن لتطبيق مراقب ربط وظيفة التحديث لكل تعليمة في محلل مع الحقول المقابلة للنموذج ؛
قم بتنفيذ مراقب لمراقبة تغيير قيمة جميع مجالات الكائن ، وبمجرد حدوث التغيير ، يمكن الحصول على القيمة الأخيرة ويمكن تشغيل رد الاتصال الإخطار ؛
استخدم المراقب لإنشاء مراقبة للنموذج في المراقب. عندما تتغير قيمة في النموذج ، يتم تشغيل المراقبة. بعد حصول المراقب على القيمة الجديدة ، يستدعي وظيفة التحديث المرتبطة في الخطوة 2 ، والتي يمكن أن تحقق الغرض من تحديث العرض أثناء تغيير البيانات.
مثال التأثير
أولاً ، دعونا نلقي نظرة على مثال الاستخدام النهائي ، وهو مشابه لتثبيت أطر عمل MVVM الأخرى:
<div id = "mobile-list"> <h1 v-text = "title"> </h1> <ul> <li v-for = "item in brands"> <b v-text = "item.name"> </b> <span v-show = "showrank"> rank: {{item.rank} document.queryselector ('#mobile-list') ؛ var vm = new mvvm (element ، {'title': 'mobile list' ، 'showrank': true ، '{{{' name ':' Apple '،' Rank ': 1} ، {' name ':' Galaxy '،' Rank ': {' name ':' Oppo '، 3}]] // => <H1> قائمة رتبة جوال Top 3 </h1>قسم الوحدة النمطية
قمت بتقسيم MVVM إلى خمس وحدات لتنفيذ: برنامج التحويل البرمجي للتجميع ، المحلل ، عرض تحديث وحدة التحديث ، مراقب وحدة الاشتراك في البيانات ، ومراقب وحدة الاستماع إلى البيانات. يمكن وصف العملية بإيجاز على النحو التالي: بعد أن يقوم برنامج التحويل البرمجي بتجميع الأمر ، يتم تسليم معلومات التعليمات إلى المحلل المحلل لتحليل التحليل. يقوم المحللون بتحديث القيمة الأولية ويشترك في مراقب التغييرات في البيانات. يراقب المراقب يتغير البيانات ثم يعيدها إلى المراقب. يقوم المراقب بإخطار تحديث نتيجة التغيير ويجد وظيفة التحديث المقابلة لتحديث العرض.
يتم عرض العملية أعلاه في الشكل:
فيما يلي وصف للمبادئ الأساسية لتنفيذ هذه الوحدات الخمسة (يتم نشر الرمز فقط على الأجزاء الرئيسية ، يرجى الانتقال إلى github لتنفيذها الكامل)
1. ترجمة وحدة التحويل البرمجية
تتمثل مسؤولية التحويل البرمجي بشكل أساسي في مسح التعليمات واستخراجها لكل عقدة من العنصر. نظرًا لأن عملية التجميع والتحليل ستجتاز شجرة العقدة بأكملها عدة مرات ، من أجل تحسين كفاءة التجميع ، في مُنشئ MVVM ، قم بتحويل العنصر أولاً إلى نسخة من شظايا المستندات. كائن التجميع هو جزء المستند هذا ويجب ألا يكون عنصرًا مستهدفًا. بعد تجميع جميع العقد ، تتم إضافة جزء المستند إلى العقدة الحقيقية الأصلية.
ينفذ VM.complieElement المسح واستخراج التعليمات لجميع العقد من العنصر:
vm.compileElement = function (جزء ، جذر) {var node ، childnodes = fragment.childnodes ؛ // مسح عقدة الطفل لـ (var i = 0 ؛ i <childnodes.length ؛ i ++) {node = childnodes [i] ؛ عقدة الطفل للعقدة الطفل إذا (node.childnodes.length) {this.compileElement (node ، false) ؛}}ستعمل طريقة vm.compileallnodes على تجميع كل عقدة في هذا. $ uncompilenodes (اترك معلومات التعليمات إلى المحلل). بعد تجميع عقدة ، ستتم إزالتها من قائمة انتظار ذاكرة التخزين المؤقت. في الوقت نفسه ، تحقق من هذا. $ uncompilenodes.length عندما الطول === 0 ، فهذا يعني أن جميع التجميع قد اكتملت. يمكنك إلحاق شظايا المستند إلى العقدة الحقيقية.
2. تحليل وحدة تحليل التعليمات
عندما يقوم برنامج التحويل البرمجي بإخراج التعليمات من كل عقدة ، يمكن إرسالها إلى المحلل المحلل للحلية. كل تعليمات لها طريقة تحليل مختلفة. تحتاج جميع الإرشادات فقط إلى القيام بأمرين: الأول هو تحديث قيمة البيانات إلى العرض (الحالة الأولية) ، والآخر هو الاشتراك في وظيفة التحديث في مراقبة تغيير النموذج. هنا نستخدم تحليل النص V كمثال لوصف طريقة التحليل العام للتوجيه:
parser.parsevtext = function (node ، model) {// احصل على القيمة الأولية المحددة في النموذج var text = this. $ model [model] ؛ {node.textContent = last ؛ // updater.updatenodetextContent (Node ، text) ؛}) ؛}3. مراقب وحدة الاشتراك في البيانات
في المثال السابق ، يوفر Watcher طريقة مشاهدة للاشتراك في تغييرات البيانات. معلمة واحدة هي نموذج حقل النموذج والآخر هو وظيفة رد الاتصال. يتم تشغيل وظيفة رد الاتصال من خلال المراقب. تم تمرير القيمة الجديدة والقيمة القديمة القديمة في المعلمة. بعد حصول المراقب على القيمة الجديدة ، يمكنه العثور على رد الاتصال المقابل (وظيفة التحديث) للنموذج لتحديث العرض. وظائف النموذج والتحديث هي علاقة واحدة لأعضاء ، أي أن النموذج يمكن أن يحتوي على العديد من وظائف رد الاتصال (وظائف التحديث) التي تتعامل معها ، على سبيل المثال: V-Text = "title" و V-HTML = "title" تشترك في حقل نموذج بيانات.
إضافة اشتراك البيانات إلى Watcher.Watch طريقة تنفيذ::
watcher.watch = function (الحقل ، رد الاتصال ، السياق) {var callbacks = this. $ watchcallbacks ؛ if (! object.hasownproperty.call (هذا. $ model ، الحقل)) {console.warn [] ،عندما يتغير حقل حقل نموذج البيانات ، يقوم Watcher بإعداد جميع عمليات الاسترجاعات في مجموعة ذاكرة التخزين المؤقت التي اشتركت في الحقل.
4. مراقب وحدة مراقبة البيانات
المراقب هو الأساس الأساسي لتنفيذ MVVM بالكامل. قرأت مقالًا يقول أن OO (Object.Observe) سوف يشعل ثورة ربط البيانات وتجلب تأثيرًا كبيرًا على الواجهة الأمامية. لسوء الحظ ، تخلى مسودة ES7 OO! لا يوجد دعم للمتصفح في الوقت الحاضر! لحسن الحظ ، هناك أيضًا كائن.
// اعتراض أساليب الحصول على وضبط خاصية prop لكائن الكائن. تشغيل تغيير رد الاتصال this.triggerChange (Prop ، NewValue ، Oldvalue) ؛}}}) ؛
ثم هناك سؤال آخر: كيفية مراقبة عمليات الصفيف (الدفع ، التحول ، إلخ)؟ يتم تنفيذ جميع أطر عمل MVVM عن طريق إعادة كتابة النموذج الأولي للمصفوفة:
Observer.RewRiteArrayMethods = function (Array) {var self = this ؛ var arrayproto = array.prototype ؛ var arraymethods = object.create (ArrayProto) ؛ var methodes = 'pop | shift | unshift | splice | revers'.split (' | ') ؛ methods.foreach (function (method) {object.defineProperty (arraymethods ، method ، function () {var i = enduments.length ؛ var original = arrayproto [method] ؛ var args = new array (i) ؛ الطريقة) ؛ نتيجة الإرجاع ؛}) ؛}) ؛ صفيف .__ proto__ = arraymethods ؛}تتم الإشارة إلى طريقة التنفيذ هذه من VUE. أعتقد أنه يتم استخدامه بشكل جيد للغاية ، ولكن لا يمكن الاستماع إلى سمة الطول للمصفوفة ، لذلك في MVVM ، يجب تجنب عملية الطول.
5. عرض تحديث وحدة التحديث
يعد Updater أسهل بين الوحدات الخمس ، فأنت بحاجة فقط إلى أن تكون مسؤولاً عن وظيفة التحديث المقابلة لكل تعليمات. بعد سلسلة من القذف وترك النتيجة النهائية إلى التحديثات لعرض أو تحديثات الأحداث ، على سبيل المثال ، فإن وظيفة التحديث لنص V هي:
updatater.updatenodetextContent = function (node ، text) {node.textContent = text ؛}تحديث وظيفة V-bind: النمط:
updatater.updatenodestyle = function (node ، property ، value) {node.style [propperty] = value ؛}تنفيذ ربط البيانات ثنائية الاتجاه
يعد ربط البيانات ثنائية الاتجاه لعناصر النماذج أحد أكبر ميزات MVVM:
في الواقع ، مبدأ التنفيذ لهذه الوظيفة السحرية بسيطة للغاية. لا يوجد سوى شيئين يجب القيام به: أحدهما هو تحديث قيمة النموذج عندما تتغير البيانات ، والآخر هو تحديث البيانات عندما تتغير قيمة النموذج ، بحيث تكون قيمة البيانات مرتبطة بقيمة النموذج.
يمكن بسهولة إجراء تغييرات البيانات لتحديث قيم النماذج باستخدام وحدة المراقبة المذكورة أعلاه:
Watcher.Watch (النموذج ، الوظيفة (الأخيرة ، القديم) {input.value = last ؛}) ؛ 'لتحديث البيانات في النموذج ، تحتاج فقط إلى الاستماع إلى النموذج يستحق تغيير الأحداث في الوقت الحقيقي وتحديث الحقول المقابلة لنموذج البيانات:
var model = this. $ model ؛ input.addeventListenr ('change' ، function () {model [field] = this.value ؛}) ؛ 'نماذج أخرى راديو ومربع الاختيار واختيار هي نفس المبدأ.
ما سبق ، تم شرح العملية بأكملها وأفكار التنفيذ الأساسية لكل وحدة. في المرة الأولى التي نشرت فيها مقالًا في المجتمع ، فإن مهارات تعبير اللغة الخاصة بي ليست جيدة جدًا. إذا كان هناك أي كلمات خاطئة وأشياء سيئة مكتوبة ، آمل أن يتمكن الجميع من انتقادها وتصحيحها!
خاتمة
أحاول هذا MVVM.JS البسيط لأنني استخدمت Vue.js في مشروع الإطار الخاص بي ، لكنني استخدمت للتو نظام التعليمات الخاص به. تم استخدام الكثير من الوظائف فقط حوالي ربع. اعتقدت أنه سيكون كافياً فقط لتنفيذ ربط البيانات و REFRESH. نتيجة لذلك ، لم أجد مكتبة JavaScript هذه ، لذلك قمت بإنشاء مثل هذه العجلة بنفسي.
على الرغم من أن الوظائف والاستقرار أقل بكثير من أطر عمل MVVM الشائعة مثل VUE ، وقد يكون تنفيذ الكود قاسيًا نسبيًا ، فقد تمت إضافة الكثير من المعرفة عن طريق بناء هذا التقدم في القذف!
في الوقت الحاضر ، يقوم MVVM.JS الخاص بي فقط بتنفيذ الوظيفة الأساسية. سأستمر في تحسينه وتقويته في المستقبل. إذا كنت مهتمًا ، فيرجى مناقشة وتحسينه معًا ~