English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية

تحليل مبادئ Vue.js وشرح وحدة observer

مقدمة

مكتبة observer هي أكثر مكتبات Vue الأساسية أهمية (بالنسبة لي)، حيث يمكنها تحقيق تحديث الديناميكية بين الرؤية والبيانات، ويعتمد هذا كليًا على دعم observer.

ملاحظة:هذا المقال مخصص لتحليل [email protected]

يتم وضع مكتبة observer في موقع src/core/observer في مشروع Vue، والمكتبة مقسومة إلى هذه الأجزاء:

  1. Observer: ملاحظ البيانات، يجعل عمليات القراءة والكتابة لجسم البيانات تحت المراقبة الخاصة به
  2. Watcher: مشترك البيانات، يتم إعلام Watcher بتغيير البيانات، ثم يتم تنفيذ العمليات المناسبة من قبل Watcher، مثل تحديث الرؤية
  3. Dep: رابط Observer و Watcher، عند تغيير البيانات، يتم ملاحظة Observer، ثم يتم إعلام Watcher من قبل Dep

الشكل التوضيحي التالي:

Observer

يتم تعريف كلاس Observer في src/core/observer/index.js، لننظر في بناء كلاس Observer أولاً

constructor (value: any) {
 this.value = value
 this.dep = new Dep()
 this.vmCount = 0
 def(value, '__ob__', this)
 إذا كان Array.isArray(value) {
 const augment = hasProto
 ? protoAugment
 : نسخة Augment
 augment(value, arrayMethods, arrayKeys)
 this.observeArray(value)
 }
 this.walk(value)
 }
}

القيمة هي الجسم المطلوب مراقبته، يتم إضافة خاصية __ob__ إلى القيمة في بناء المحول، كعلامة على أن القيمة قد تم مراقبتها من قبل Observer. إذا كانت القيمة هي صفوف، يتم استخدام observeArray لمرور القيمة، وتنفيذ وظيفة observe على كل عنصر من القيمة لمراقبته. إذا كانت القيمة هي جسم، يتم استخدام walk لمرور كل مفتاح في القيمة، وتنفيذ وظيفة defineReactive على كل مفتاح للحصول على التحكم في set/get لهذا المفتاح.

توضيح وظائف بعض الدوال المستخدمة أعلاه:

  • observeArray: مرور الصفوف، تنفيذ وظيفة observe على كل عنصر من الصفوف
  • observe: يتم فحص وجود خاصية __ob__ في العنصر، إذا كانت موجودة، فإن ذلك يعني أن العنصر بالفعل تحت مراقبة Observer، إذا لم تكن موجودة، يتم إنشاء Observer لمراقبة العنصر (هناك بعض منطق التحكم الأخرى، ولكن لا يتم ذكرها لتسهيل الفهم)
  • walk: يمرر على كل key من العنصر، ويتم تنفيذ defineReactive على كل key في العنصر
  • defineReactive: يتم تعيين key الخاص بالعنصر باستخدام Object.defineProperty، مما يسمح بالتقاطع مع عمليات set/get للقيمة. عادة ما يتم تنفيذ get من قبل ملاحظة Watcher، حيث يتم إضافة ملاحظة Watcher إلى قائمة الاعتماد في Dep، وعند إجراء set من الخارج، يتم إعلام جميع الملاحظات التي تعتمد عليها من خلال notify من Dep.

إذا لم تفهم النصوص أعلاه، يمكنك الرجوع إلى الشكل التالي:

Dep

Dep هو رابط بين Observer و Watcher، يمكن اعتبار Dep كنظام اشتراك يخدم Observer. ياشركر Watcher في Dep، وعندما يغير Observer البيانات، يتم إعلام جميع الملاحظات التي اشتركت بالتحديث من خلال Dep.

يقدم Dep عدة واجهات:

  • addSub: يتم تقديم الملاحظة كمعامل، ويتم إضافة ملاحظة Watcher إلى قائمة الاعتماد
  • removeSub: يعمل بشكل عكسي مع addSub، حيث يتم إزالة ملاحظة Watcher من قائمة الاعتماد
  • depend: يوضع Dep.target على هذا الملاحظة الحالية التي يجب معالجتها، يتم استدعاء depend لإضافة ملاحظة Watcher هذه إلى طريقة addDep، يمكن الاطلاع على وظيفة addDep في شرح Watcher التالي
  • notify: إعلام جميع الملاحظات في قائمة الاعتماد بالتحديث

Watcher

Watcher يستخدم للاشتراك في التغيرات في البيانات وتنفيذ العمليات المطلوبة (مثل تحديث الواجهة). يعرف بناء Watcher كالتالي:

المؤسس (vm, expOrFn, cb, options) {
 هذا.vm = vm
 vm._watchers.push(this)
 // options
 إذا (options) {
 هذا.deep = !!options.deep
 هذا.user = !!options.user
 هذا.lazy = !!options.lazy
 هذا.sync = !!options.sync
 }
 this.deep = this.user = this.lazy = this.sync = false
 }
 this.cb = cb
 this.id = ++uid // uid for batching
 this.active = true
 this.dirty = this.lazy // for lazy watchers
 this.deps = []
 this.newDeps = []
 this.depIds = new Set()
 this.newDepIds = new Set()
 this.expression = process.env.NODE_ENV !== 'production'
 ? expOrFn.toString()
 : ''
 if (typeof expOrFn === 'function') {
 this.getter = expOrFn
 }
 this.getter = parsePath(expOrFn)
 if (!this.getter) {
 this.getter = function () {}
 process.env.NODE_ENV !== 'production' && warn(
 `فشل مراقبة المسار: "${expOrFn}" ` +
 
 'للتحكم الكامل، استخدم دالة بدلاً من ذلك.',
 vm
 )
 }
 }
 this.value = this.lazy
 ? undefined
 : this.get()
}

في المعلمات، vm يمثل نموذج المكون، expOrFn يمثل الحقل البيانات الذي يتم الاشتراك فيه (مثل سلسلة من الأحرف، مثل a.b.c) أو دالة يجب تنفيذها، cb يمثل دالة التبليغ بعد تشغيل watcher، options هو نموذج الخيارات، يحتوي على تكوينات مثل deep، user، lazy وما إلى ذلك

على نموذج watcher هذه الطرق:

  • get: يضبط Dep.target إلى نموذج الحالة الحالي، في الداخل يدعو هذا.getter، إذا في هذا الوقت بعض البيانات التي يتم مراقبةها بواسطة Observer تمت استعادتها، فإن نموذج الحالة الحالي الحالي سيتم الاشتراك فيه تلقائيًا في نموذج Dep للبيانات
  • addDep: استقبال المعامل dep (مثال Dep)، وتسجيل اشتراك المشاهد الحالية في dep
  • cleanupDeps: إزالة المعلومات المسجلة في newDepIds و newDep حول اشتراك dep
  • update: تشغيل المشاهد على الفور أو إضافة المشاهد إلى الخط المسبق لانتظار التصفية
  • run: تشغيل المشاهد، استدعاء this.get() للحصول على القيمة، ثم تفعيل الإ回调
  • evaluate: استدعاء this.get() للحصول على القيمة
  • depend: استكشاف this.deps، وتسجيل اشتراك المشاهد الحالية في جميع dep
  • teardown: إزالة جميع الاشتراكات الخاصة بالمشاهد الحالية

طرق قائمة

في الملف src/core/observer/array.js، قام Vue الفريق بتغيير طرق الأدوات push、pop、shift、unshift、sort、splice و reverse في قائمة Vue، مما يؤدي إلى تفعيل dep.notify() تلقائيًا عند استدعاء هذه الطرق في قائمة، مما يلغي مشكلة عدم تفعيل التحديث بعد تغيير القائمة باستخدام هذه الطرق.

هناك أيضًا توضيح في وثائق Vue الرسمية لهذا: http://cn.vuejs.org/v2/guide/list.html#الطرق-التغيرية

الخلاصة

هذا هو محتوى المقال كله، آمل أن تكون محتويات هذا المقال قد ساعدتكم في التعلم أو العمل، إذا كان لديكم أي استفسارات، يمكنكم ترك تعليقات للتفاعل.

بيان: محتوى هذا المقال تم جمعه من الإنترنت، ويملك حقوق النشر أصحاب الملكية، تم جمع المحتوى من قبل المستخدمين على الإنترنت الذين قدموه بأنفسهم، ولا يمتلك هذا الموقع حقوق الملكية، لم يتم تعديل المحتوى بشكل إنساني، ولا يتحمل هذا الموقع أي مسؤولية قانونية ذات صلة. إذا كنت قد وجدت محتوى يشتبه في انتهاك حقوق النسخ، فلا تتردد في إرسال بريد إلكتروني إلى: notice#oldtoolbag.com (عند إرسال البريد الإلكتروني، يرجى استبدال #بـ @) للإبلاغ، وقدم الدليل على الدليل، وسيتم حذف المحتوى المزعوم بسرعة إذا تم التحقق منه.

تحب أن ترى