
صادفت مؤخرًا نقاشًا مثيرًا للاهتمام حول Full Stack Radio -
Bulding Better UI Components with State Machines . كانت النقطة أن مفهوم جهاز الحالة يمكن أن يساعد في تطوير مكونات Vue. بدأت أنظر إلى الحلول الجاهزة ، لكنها لم تكن بهذه البساطة ، وأردت أن أقدم تطبيقًا أبسط ، وأريد أن أتحدث عنه في هذا المقال. قد تكون المقالة مفيدة ليس فقط لأولئك الذين يستخدمون Vue ، ولكن أيضًا لمستخدمي Angular ، React ، إلخ ، وكذلك لمبرمجي "الطوائف" الأخرى.
تطرقت المناقشة إلى موضوع قريب من كل من كتب المكونات. تخيل. أنك تكتب مكونًا يطلب البيانات ، وتحتاج إلى عرض المغزل أثناء تشغيل الاستعلام. عادة في مثل هذه الحالات تقوم بإنشاء متغير منطقي isLownload. في البداية ، isLownload = false ، وقبل طلب البيانات ، يمكنك تعيين متغير isLownload إلى true. بعد وصول البيانات ، يمكنك تعيينها مرة أخرى على "خطأ". يرتبط الدوار الدوار isLownload.
هذا النهج يعمل بشكل رائع. لكن المكون نادراً ما يكون بهذه البساطة. وفي سياق العمل ، لا يزال من الضروري إنشاء متغيرات منطقية تخزن حالات مختلفة. المشكلة هي أنه إذا كان لديك متغير حالة واحد ، فإنه يولد حالتين ، ومتغيرين منطقيين لهما بالفعل أربع حالات ، ثلاثة إلى ثمانية ، إلخ. والمشكلة هي أن المبرمج قد يرتكب خطأ ولن يقوم بمعالجة أي حالات قد يدخل فيها النظام. وهذا يؤدي إلى خطأ. بالإضافة إلى ذلك ، من الصعب فهم مثل هذا المكون ومن الضروري تهيئة الظروف.
الجواب هو آلة الدولة. المبدأ بسيط - تصف الحالات التي قد يكون فيها النظام ، والانتقالات بين الولايات. إن وجود مثل هذه الآلة يمكن أن يتجنب العديد من الأخطاء ، وكذلك تحديد حالة النظام بشكل تعريفي.
هناك عدد قليل من المقالات حول هذا الموضوع (على سبيل المثال ،
Finite State Machines في Vue ، ولكن معظمها ، بعد نظرية مختصرة ، يوصي بربط إحدى المكتبات الجاهزة. على سبيل المثال ،
davidkpiano / xstate .
اعتقدت أن إكسستات كان مرهقًا جدًا وأريد أن أجرب دراجتي. بالإضافة إلى ذلك ، هذا سبب كبير لجعل نمط جديد بالنسبة لي.
هنا هو الكود للعب مع -
آلة الدولة مع Vue ، الإصدار 2 . وإليكم النسخة الخام ، بنهج مختلف قليلاً -
جهاز الدولة مع Vue ، الإصدار 1 .
لقد بدأت من المادة
آلات الدولة .
لذلك آلة الدولة:
class StateMachine { constructor (initialState, transitions) { this.state = initialState this.transitions = transitions } transition (nextState, method, params) { const transitionsArray = this.transitions[this.state] if(transitionsArray.indexOf(nextState) === -1) return this.state if(method) method(...params) this.state = nextState return this.state } }
تهيئة مثل هذا:
const machine = new StateMachine('idle', { idle: ['waitingConfirmation'], waitingConfirmation: ['idle','waitingData'], waitingData: ['dataReady', 'dataProblem'], dataReady: ['waitingConfirmation'], dataProblem: ['waitingConfirmation'] })
في أساليب المكون ، قم بإنشاء دالة انتقال:
transition(nextState, method = null, params = []) { this.machineState = machine.transition(nextState, method, params) }
في الأحداث ، نكتب على الفور أين نريد أن نذهب:
@click=“transition('waitingConfirmation')"
إذا كنت بحاجة إلى استدعاء طريقة المكون في نفس الوقت ، فاكتب هذا:
@click="transition('waitingData', getData, [222])”
المعلمة الثانية هي طريقة المكون الذي يجب استدعاؤه بهذا الانتقال.
المعلمة الثالثة هي مجموعة من المتغيرات لهذه الطريقة.
داخل الأساليب ، الدعوة هي:
this.transition('dataReady')
أنا عمداً لم أخفي الأزرار باستخدام v-if ، حتى الآن ، اجعل لون الخط بلون رمادي. لكن من الواضح أن النقر فوقها لا يعمل إذا كان الجهاز لا يسمح بذلك.
بشكل عام ، كل شيء يعمل ، الحل سهل للغاية. والأهم من ذلك ، تمكنا من وصف تشغيل المكون بشكل تعريفي. أنا شخصياً مستعد تقريبًا لتطبيق هذا النهج في تطبيق حقيقي ، لكنني أود أن أفهم إيجابيات وسلبيات هذا النهج ، والاستماع إلى نصيحة الخبراء الأكثر خبرة.