Angular جيد في إطار MVVM ، ولكن مع مثل هذا الإطار الكبير والشامل ، فإنه ليس منخفضًا للتعلم ، وسيستغرق الأمر أسبوعًا أو أسبوعين على الأقل للبدء. تركز KnockOutJs على ربط البيانات ويمكن استخدامها في يوم واحد أو يومين فقط ، لذلك يجب ألا تكون تكلفة التعلم منخفضة للغاية! في عصر يكون فيه التطور الأمامي سريعًا للغاية ، فإن تكلفة التعلم هي أيضًا عامل يجب مراعاته. في كثير من الأحيان ، فإن مشاريعنا ليست معقدة ، ولا تحتاج إلى إطار عالمي. إنهم بحاجة إلى أدوات بسيطة وسهلة.
قبل خروج المغلوب
لنفترض أننا نقوم ببناء نظام أوامر ونحتاج إلى عرض سعر الوحدة للمنتج ، وبعد ذلك يمكننا حساب السعر الإجمالي بناءً على كمية الإدخال وعرضه. من السهل أيضًا تحقيقه باستخدام الكود الأصلي ، وهو التأثير هو:
الرمز كما يلي:
<!-رمز html-> السعر: <span id = "price"> </span> <br /> الحساب: <input type = "text" id = "account" value = "" placeholder = "الرجاء إدخال الكمية" /> <br /> sum: <span id = "sum" </span> // js codevar pricenode = " document.getElementById ('حساب') ، sumnode = document.getElementById ('sum') ، السعر = 100 ، الحساب = 11 ، sum = price * حساب ؛ // تهيئة. pricenode.innertext = price ؛ accountnode.value = account ؛ sumnode.textContent = // مراقبة إدخال المستخدم من layer layer accountnode.addeventListener ('keydown' ، function (e) {window.settimeout (function () {accountnode.value ؛ sum = price * account ؛حسنًا ، الأمر بسيط للغاية! أوه ، بالمناسبة ، نعرض 50 عنصرًا في وقت واحد ، وهناك 10 أنواع من الشاشات ، بالإضافة إلى العديد من العروض الترويجية مثل شراء 5 صناديق من Okamoto والحصول على عصا العجين المقلي ...
لذلك ، أنت تعرف مشكلة التنفيذ الأصلي:
• مع زيادة تفاعل واجهة المستخدم والبيانات ، نمت كمية الكود بسرعة ويصعب الحفاظ عليها
• يصعب إدارة الأسماء المستندة إلى استفسارات DOM أو معرفها أو فئة
• اقتران الرمز العالي ، يصعب إعادة استخدامه
مقدمة إلى knockoutjs
يبدو أن Knockoutjs (المشار إليها فيما يلي باسم KO) بحل المشكلات المذكورة أعلاه. إنها مكتبة MVVM خفيفة الوزن تركز على تنفيذ ربط البيانات والطرق. لا يوفر فصول واجهة المستخدم ووظائف التوجيه ، وهو سريع للغاية للبدء. في الوقت نفسه ، نظرًا لأن KO قد خرجت منذ عدة سنوات ، فقد أصبح إطارًا ناضجًا نسبيًا. عند القيام ببعض الصفحات التي تعرض بشكل أكثر ديناميكية ، فإن KO هو بلا شك خيار أفضل. لن أقول الكثير عن MVVM ، مجرد صورة للارتباك:
يعتمد KO على ثلاث ميزات أساسية (مقدمة إلى الموقع الرسمي):
1. ملاحظات وتتبع التبعية: استخدم Observables لإعداد سلسلة علاقة ضمنية بين بيانات النموذج لتحويل البيانات والربط.
2. الارتباطات التعريفية: استخدم بناء جملة بسيط وسهل القراءة لربط البيانات النموذجية بسهولة لعناصر DOM.
3. templating: محرك القالب المدمج ، اكتب بسرعة عروض واجهة المستخدم المعقدة لبيانات النموذج الخاصة بك.
استخدام KO بسيط للغاية. ما عليك سوى تنزيله مباشرة إلى الموقع الرسمي (http://knockoutjs.com/index.html) وقدمه مع <script>.
كائنات يمكن ملاحظتها
أعد كتابة المثال أعلاه باستخدام KO (السعر المخصص ، الذي كان أحد رغبات طفولتي):
الرمز يشبه هذا:
<!-HTML Code-> <div id = "one"> السعر: <input type = "text" data-bind = "value: price" placeholder = "الرجاء إدخال سعر الوحدة" /> <br /> الحساب: <input type = "text" data-bind = "value: account" placeholder = "الرجاء إدخال الرقم" /br /> <span data-pind = = الوظيفة (p ، a) {// تعيين ككائن قابل للملاحظة وتهيئة this.price = ko.observable (p) ؛ this.account = ko.observable (a) ؛ // عند استدعاء وظيفة KO ، سيتم تمرير ذلك. هذا. 10) ؛ // تطبيق هذا الربط ، ويبدأ الربط في سريان KO.ApplyBindings (VM) ؛1) دعونا نلقي نظرة على رمز HTML أولاً:
يمكنك أن ترى أنه يتم إضافة زوج قيمة مفتاح مثل Data-Bind = "XX: OO" إلى كل علامة. هذا هو بناء جملة الربط من KO. ماذا تمثل xxoo؟ " يبدو OO وكأنه متغير ، لكنه ليس متغيرًا ، ولكن كائن دالة. يمكن تنفيذ هذه الوظيفة (مع A ()) الحصول على القيمة المرتبطة المقابلة. من خلال XXOO ، يمكن ربط سمات أو أحداث عنصر ما بكائنات الوظيفة في JS (إذا كان XXOO ، يجب أن تكون مسؤولاً عن بعضها البعض) ، وهذا هو الربط التعريفي لـ KO. إن تعريف الربط هو في الواقع وضع مراقب ، ولكن هذا ملزم ثنائي الاتجاه. يشترك الناشر والمشترك في رسائل بعضهما البعض. هذا هو الربط ثنائي الاتجاه من MVVM. تتمثل نتيجة الربط ثنائي الاتجاه في KO في أنه يمكن لأحد الطرفين تحديث الطرف الآخر تلقائيًا عن طريق التغيير ، أي أن طبقة البيانات وطبقة العرض يتم ربطها بإحكام من خلال ViewModel. تأثير الربط مشابه لـ:
2) دعونا نلقي نظرة على رمز JS:
يمكنك أن ترى أنه يتم تعريف كائن ViewModel في JS ، ويتم تشغيل OO المرتبط في HTML في الكائن. هناك عمليتان رئيسيتان هنا: ko.observable () و Ko.PureCoptated ().
• Ko.Observable (P): انظر الاسم ، هذه هي طريقة تعيين الكائنات التي يمكن ملاحظتها. المعلمة التي تم تمريرها P هي القيمة المهيئة. يمكن أن تكون المعلمات هنا نوع البيانات الأساسي أو كائن JSON. بعد تعيينه على أنه يمكن ملاحظته ، فهذا يعني أن النظام سيراقب هذه القيمة طوال الوقت. ما إذا كانت P في ViewModel أو P في تغييرات الكائن المربوطة ستتسبب في حدث تحديث ، وسيتم تحديث جميع الأماكن التي تستخدم هذه القيمة إلى أحدث حالة. من الواضح أن الكائنات التي يمكن ملاحظتها تستغرق أداءً نسبياً ، لذلك بالنسبة للقيم التي لا تتطلب تغييرات ديناميكية (مثل الأسعار) ، لا يتم تعيينها ككائنات يمكن ملاحظتها. بالطبع ، لا يزال يتعين وضعه في ViewModel للتهيئة المركزية.
• ملاحظة: الكائن الذي يمكن ملاحظته الذي تم إرجاعه بواسطة Ko.Observable (P) هو كائن دالة ، لذلك تحتاج إلى استخدام Price () لقراءة الكائن الذي يمكن ملاحظته ؛ وبالمثل ، يتطلب تعيين الكائن الذي يمكن ملاحظته السعر (NewValue) لاستخدام السعر (NewValue). ما هو أكثر مراعاة هو أنه عند الإعداد ، فإنه يدعم كتابة السلسلة: ViewModel.Price (100) .Account (10).
• KO.PURECOMPUTED () هو ما يسمى تتبع التبعية. هنا هو سعر الوحدة * الكمية تساوي السعر الإجمالي. لاحظ أنه لا يمكنك استخدام this.sum = this.price () * this.account () ؛ لتحديد مجموع. لا يمكن أن تحدد طريقة الكتابة هذه بشكل ديناميكي الكائن المرتبط ، ولكن يغير بشكل ديناميكي متغير SUM ، ولكن هناك حاجة إلى عمليات أخرى لتحديث الكائن المرتبط. لذلك ، يجب تعيين قيم الربط المتعلقة بالحسابات باستخدام وظيفة حساب KO. بالطبع ، كائن الوظيفة التي تم إرجاعها هو أيضًا كائن دالة. بالإضافة إلى ذلك ، لدى KO أيضًا وظيفة محسوبة ، والتي يمكن تعيينها أيضًا ، ولكن يوصى باستخدام Pure لتحسين الأداء.
• انتبه إلى طريقة الكتابة هنا: ko.purecospated (fn ، هذا) ، أي ربط fn بنطاق ViewModel ، والذي هو في الواقع المكالمة/تطبيقها في JS. نظرًا لأن هذا كائن KO عند تنفيذ وظائف KO الداخلية ، من أجل الحصول على نطاق كائن ViewModel ، يجب نقل هذا إلى طريقة الكتابة أعلاه. بالطبع ، يمكنك أيضًا استخدام ذلك لحفظ كائن ViewModel خارج وظيفة KO ، ثم استخدام ذلك داخل وظيفة KO للاتصال بكائن ViewModel. مثله:
var that = this ؛ this.sum = ko.pureCompated (function () {return that.price () * that.Account () ؛}) ؛بعد تحديد مُنشئ ViewModel ، يتم إنشاء كائن ViewModel ، ثم يتم استخدام طريقة ko.applybindings () لجعل المفعول المفعول للربط. لا تفوت هذه الخطوة.
وضع صفحة بسيط باستخدام KO:
<!-رمز html-> <span data-bind = "text: bindText"> </span> // JS codevar viewmodel = {bindText: ko.observable ('initvalue')} ؛ ko.applybindings (viewModel) ؛لتلخيص ، هو: استخدام البيانات- bind = "XX: OO" لإعلان الربط في HTML ، وإنشاء عرض ViewModel في JS وضبط كائن يمكن ملاحظته ، وأخيراً تطبيق الربط.
صفيف كائن يمكن ملاحظته
دعونا نلقي نظرة على استخدام صفائف الكائنات التي يمكن ملاحظتها. في KO ، لا يمكن خلط المصفوفات والمتغيرات مثل JS. بالنسبة لكائنات الصفيف ، تحتاج إلى استخدام ko.observablearray ([... ، ...]) بنفس الطريقة. وبالمثل ، يمكن أن تكون عناصر الصفيف من الأنواع الأساسية أو كائنات JSON. تحتوي صفيف الكائنات الملحوظة في KO على سلسلة من طرق تشغيل الصفيف ، مثل Slice () ، sort () ، push () ، إلخ. التأثير هو نفسه طرق تشغيل صفيف JS الأصلية. سيتم إخطار الفرق الوحيد بين التغييرات التي تم إجراؤها من خلال طريقة KO إلى المشترك لتحديث الواجهة ، لكن طريقة JS لن تحديث الواجهة. هنا مثال بسيط:
<!-رمز html-> <تحديد data-bind = "الخيارات: list"> </select> // js codevar vm = {// list: ko.observablearray () list: ko.observablearray (['luffy' ، 'zoro' ، 'sanji']} ؛ ko.applybindings (vm) ؛النقطة الرئيسية: تراقب KO حالة الصفيف ، وليس حالة العنصر نفسه. وهذا يعني أنه عندما تتغير حالة الصفيف (إضافة عناصر) ، سيتم تشغيل حدث KO للتسبب في تحديث الكائن المرتبط ، ولكن لن تتم مراقبة التغييرات في العناصر الموجودة داخل الصفيف (مثل تغييرات القيمة) ولا يمكنها تشغيل حدث KO. على سبيل المثال:
لن يؤدي استخدام الطرق الأصلية لتغيير Luffy إلى Lucy في وحدة التحكم إلى تحديث صفحة واجهة المستخدم ، أثناء استخدام صفيف KO لتغيير الصفيف على الفور. تجدر الإشارة إلى أنه عند الانتعاش ، سيتم أيضًا تحديث التغييرات السابقة (Luffy> Lucy). بمعنى آخر ، تغيرت المتغيرات في ذاكرة JS بالفعل ، ولكن لا يزال هناك نقص في إجراء لتحديث DOM. كما ترون هنا ، فإن طريقة قراءة صفيف هي VM.List () [0] ، لأن القائمة هي أيضًا كائن وظيفة ، وتنفيذ قيمة الإرجاع هو محتوى القائمة الذي نريده. وبالمثل ، يمكنك إعادة تعيين مجموعة الكائنات التي يمكن ملاحظتها عبر VM.List (["Girl" ، "Girl"]) وتحديث واجهة المستخدم على الفور.
إذا كنت بحاجة إلى رد فعل تغييرات عناصر الصفيف ديناميكيًا على واجهة المستخدم ، فأنت بحاجة إلى تعيين عناصر الصفيف على الكائنات التي يمكن ملاحظتها ، ثم استخدام طريقة KO لتغيير قيمة عنصر الصفيف. لاحظ أنه هو استخدام قائمة طريقة KO () [0] ("Lucy")!
هناك نوعان من الطرق لتشغيل صفائف الكائنات التي يمكن ملاحظتها. أحدهما هو نفس اسم طريقة صفيف JS الأصلية: البوب ، الدفع ، التحول ، غير الهاوية ، عكس ، فرز ، لصق. هذا الجزء هو نفس استخدام وتأثيرات طريقة JS الأصلية ، لذلك لن أكررها مرة أخرى.
بعض الطرق الأخرى غير متوفرة في JS ، وخاصة على النحو التالي:
• إزالة (sumerItem) - احذف جميع عناصر العناصر ذات القيم المتساوية إلى SumerItem وإعادتها في شكل صفيف. ما يعنيه هذا هنا هو أنه لا يمكنك حذف قائمة العناصر الأولى مباشرة. Remove (0) ولكن استخدم قائمة النماذج. Remove (list () [0]) لحذفها. باختصار ، يجب أن تكون المعلمة التي تم تمريرها هي قيمة عنصر العنصر. يمكن استخدامه في شكل قائمة () [0] ، أو يمكنك إدخال سلسلة القيمة مباشرة (مثل "Luffy").
• قم بإزالة (وظيفة (عنصر) {item.age <18 ؛}) - احذف جميع عناصر العناصر ذات السمات العمرية التي تقل عن 18 عامًا وإعادتها كصفيف. لا يختلف هذا الاستخدام عن وظائف المصفوفة العليا ذات الترتيب العادي. يتم تمرير العنصر كمعلمة لوظيفة ترتيب أعلى. عند التكرار من خلال الصفيف ، يتم حذف العنصر عندما تكون قيمة الإرجاع لوظيفة الترتيب الأعلى هي القيمة الحقيقية ، وإلا فإنها ستنتقل إلى العنصر التالي.
• removeall (['chad' ، 132 ، undefined]) - قم بإزالة جميع عناصر العناصر ذات القيم التي تساوي "تشاد" أو 123 أو غير محددة وإعادتها كصفيف.
• REMOVEALL () - يزيل جميع العناصر والعودة كصفيف.
نصائح: عند التعامل مع الكائنات التي يمكن ملاحظتها ، إذا كان هناك العديد من الكائنات والتفاعلات المتكررة ، فإن الانتعاش على الفور مع كل تغيير سوف يستهلك الأداء. في هذا الوقت ، يمكنك استخدام امتداد MyobServableArray.Extend ({RateLimit: 1000}) لتعيين تحديث تأخر. على سبيل المثال ، عند إدخال العناصر بشكل مستمر في الصفيف الذي يمكن ملاحظته ، يمكنك تعيين وقت دورة قدره 1000 مللي ثانية لتركيز جميع العمليات في 1000 مللي ثانية في تحديث لتجنب تدهور الأداء الناجم عن عمليات DOM المتكررة.
لخص
تقدم هذه المقالة بشكل أساسي المفهوم الأكثر أهمية في Knockoutjs: كائنات يمكن ملاحظتها (المصفوفات). كائن يمكن ملاحظته هو في الأساس كائن وظيفة. عند تشغيل كائنات يمكن ملاحظتها من خلال طريقة KO ، يمكن تحديث واجهة المستخدم بشكل ديناميكي. هذه هي الطريقة الموصى بها. في الوقت نفسه ، يمكنك أيضًا تشغيل كائنات يمكن ملاحظتها من خلال طريقة JS الأصلية ، لكن الطريقة الأصلية لن تقوم بتحديث عرض واجهة المستخدم ، وستحتاج إلى الانتظار حتى يتم تحديث حدث التحديث التالي إلى واجهة المستخدم.