إنشاء Vuex تراجع / الإعادة البرنامج المساعد ل VueJS

الصورة


هناك العديد من المزايا لإضفاء الطابع المركزي على حالة التطبيق الخاص بك في متجر Vuex. ميزة واحدة هي أن يتم تسجيل جميع المعاملات. يتيح لك ذلك استخدام وظائف ملائمة ، مثل تصحيح وقت التشغيل ، حيث يمكنك التبديل بين الحالات السابقة لفصل المهام عن التنفيذ.


في هذه المقالة ، سأوضح كيفية إنشاء وظيفة "تراجع / إعادة" إضافية للتراجع / الإرجاع باستخدام Vuex ، والتي تعمل على غرار تصحيح الأخطاء أثناء تصحيح الأخطاء. يمكن استخدام هذه الميزة في مجموعة متنوعة من السيناريوهات ، من النماذج المعقدة إلى الألعاب القائمة على المستعرض.


يمكنك التحقق من الكود النهائي هنا على جيثب وتجربة العرض التوضيحي في Codepen هذا. قمت أيضًا بإنشاء مكون إضافي كوحدة NPM تسمى vuex-undo-redo إذا كنت ترغب في استخدامه في مشروع ما.


ملاحظة: تم نشر هذه المقالة في الأصل هنا على مدونة مطور Vue.js 2017/11/13.

التكوين المساعد


لجعل هذه الميزة قابلة لإعادة الاستخدام ، سنقوم بإنشائها كمكون إضافي لبرنامج Vue. تتطلب هذه الوظيفة منا إضافة بعض الأساليب والبيانات إلى مثيل Vue ، لذلك نقوم ببناء المكون الإضافي باعتباره mixin.


module.exports = { install(Vue) { Vue.mixin({ // Code goes here }); } }; 

لاستخدامه في مشروع ، يمكننا ببساطة استيراد البرنامج المساعد وتوصيله:


 import VuexUndoRedo from './plugin.js'; Vue.use(VuexUndoRedo); 

فكرة


ستعمل الميزة عن طريق استعادة آخر طفرة إذا أراد المستخدم إلغاءها ، ثم إعادة تطبيقها إذا أراد تكرارها. كيف نفعل هذا؟


النهج رقم 1


تتمثل الطريقة الأولى الممكنة في أخذ "لقطات" لحالة المستودع بعد كل طفرة ووضع اللقطة في صفيف. للتراجع / الإعادة ، يمكننا الحصول على اللقطة الصحيحة واستبدالها بحالة التخزين.


المشكلة في هذا الأسلوب هي أن حالة المستودع عبارة عن كائن JavaScript. عندما تضع كائن JavaScript في صفيف ، فإنك ببساطة تضع إشارة إلى الكائن. تطبيق ساذج ، مثل ما يلي ، لن ينجح:


 var state = { ... }; var snapshot = []; // Push the first state snapshot.push(state); // Push the second state state.val = "new val"; snapshot.push(state); // Both snapshots are simply a reference to state console.log(snapshot[0] === snapshot[1]); // true 

سيتطلب نهج اللقطة أن تقوم أولاً باستنساخ حالة قبل الدفع. نظرًا لأن حالة Vue تصبح تفاعلية عن طريق إضافة وظائف get and set تلقائيًا ، فإنها لا تعمل بشكل جيد مع الاستنساخ.


النهج رقم 2


هناك طريقة أخرى ممكنة تتمثل في تسجيل كل طفرة ثابتة. للإلغاء ، نعيد ضبط المتجر إلى حالته الأولية ثم ندير الطفرات مرة أخرى ؛ كل ما عدا الماضي. برد مفهوم مماثل.


بالنظر إلى مبادئ Flux ، فإن إعادة تشغيل الطفرات من نفس الحالة الأولية يجب أن يعيد إنشاء الحالة بشكل مثالي. نظرًا لأن هذا النهج أكثر نظافة من الأول ، فلنواصل.


تسجيل الطفرات


تقدم Vuex طريقة API للاشتراك في الطفرات ، والتي يمكننا استخدامها لتسجيلها. سنقوم بتعيين هذا إلى ربط created . في رد الاتصال ، نضع الطفرة في صفيف يمكن إعادة تشغيله لاحقًا.


 Vue.mixin({ data() { return { done: [] } }, created() { this.$store.subscribe(mutation => { this.done.push(mutation); } } }); 

طريقة الاستعادة


لإلغاء الطفرة ، نقوم بمسح المستودع ومن ثم إعادة تشغيل جميع الطفرات باستثناء الطفرة الأخيرة. إليك كيفية عمل الكود:


  1. استخدم طريقة صفيف pop لإزالة الطفرة الأخيرة.
  2. محو حالة المتجر باستخدام طفرة خاصة EMPTY_STATE (موضح أدناه)
  3. كرر كل طفرة متبقية ، وحددها مرة أخرى في المتجر الجديد. يرجى ملاحظة أن طريقة الاشتراك لا تزال نشطة خلال هذه العملية ، أي أنه سيتم إضافة كل طفرة مرة أخرى. حذفه على الفور مع pop .

 const EMPTY_STATE = 'emptyState'; Vue.mixin({ data() { ... }, created() { ... }, methods() { undo() { this.done.pop(); this.$store.commit(EMPTY_STATE); this.done.forEach(mutation => { this.$store.commit(`${mutation.type}`, mutation.payload); this.done.pop(); }); } } }); 

متجر التنظيف


عندما يتم استخدام هذا البرنامج المساعد ، يجب على المطور تنفيذ طفرة في مستودع التخزين الخاص به يسمى blankState. يكمن التحدي في إعادة المتجر إلى حالته الأصلية بحيث يكون جاهزًا للانتعاش من نقطة الصفر.


يجب على المطور القيام بذلك من تلقاء نفسه ، لأن المكون الإضافي الذي نقوم بإنشائه لا يملك الوصول إلى المتجر ، فقط إلى مثيل Vue. هنا مثال على التنفيذ:


 new Vuex.Store({ state: { myVal: null }, mutations: { emptyState() { this.replaceState({ myval: null }); } } }); 

بالعودة إلى المكون الإضافي الخاص بنا ، لا ينبغي إضافة طفرة emptyState إلى قائمتنا done ، حيث أننا لا نريد إعادة الالتزام بذلك أثناء عملية الاستعادة. منع هذا باستخدام المنطق التالي:


 Vue.mixin({ data() { ... }, created() { this.$store.subscribe(mutation => { if (mutation.type !== EMPTY_STATE) { this.done.push(mutation); } }); }, methods() { ... } }); 

طريقة العودة


لنقم بإنشاء خاصية بيانات جديدة ، سيتم undone عن صفيف. عندما نزيل آخر طفرة تم done أثناء عملية الاستعادة ، نضعها في هذه المجموعة:


 Vue.mixin({ data() { return { done: [], undone: [] } }, methods: { undo() { this.undone.push(this.done.pop()); ... } } }); 

الآن يمكننا إنشاء طريقة redo ستستغرق ببساطة آخر طفرة تم undone وإعادة undone بها.


 methods: { undo() { ... }, redo() { let commit = this.undone.pop(); this.$store.commit(`${commit.type}`, commit.payload); } } 

لا عودة ممكنة


إذا بدأ المستخدم الإلغاء مرة واحدة أو أكثر ثم قدم التزامًا جديدًا ، فسيتم إبطال محتويات undone . إذا حدث هذا ، يجب علينا تفريغ undone .


يمكننا اكتشاف التزامات جديدة من رد الاتصال بالاشتراك عند إضافة التزام. ومع ذلك ، فإن المنطق صعب ، حيث أن رد الاتصال ليس لديه طريقة واضحة لمعرفة ما هو الالتزام الجديد وما هو التراجع / الإعادة.


أسهل طريقة هي تعيين علامة newMutation. سيكون هذا صحيحًا بشكل افتراضي ، لكن أساليب الاستعادة والعودة ستضبطه مؤقتًا على "خطأ". إذا تم ضبط الطفرة على "صحيح" ، فسيقوم رد اتصال subscribe بمسح مجموعة undone .


 module.exports = { install(Vue) { Vue.mixin({ data() { return { done: [], undone: [], newMutation: true }; }, created() { this.$store.subscribe(mutation => { if (mutation.type !== EMPTY_STATE) { this.done.push(mutation); } if (this.newMutation) { this.undone = []; } }); }, methods: { redo() { let commit = this.undone.pop(); this.newMutation = false; this.$store.commit(`${commit.type}`, commit.payload); this.newMutation = true; }, undo() { this.undone.push(this.done.pop()); this.newMutation = false; this.$store.commit(EMPTY_STATE); this.done.forEach(mutation => { this.$store.commit(`${mutation.type}`, mutation.payload); this.done.pop(); }); this.newMutation = true; } } }); }, } 

الوظيفة الرئيسية اكتمال الآن! أضف المكوّن الإضافي إلى المشروع الخاص بك أو إلى العرض التوضيحي لاختباره.


واجهة برمجة التطبيقات العامة


في العرض التوضيحي الخاص بي ، ستلاحظ أن أزرار الإلغاء والعودة معطلة إذا لم تكن وظائفها ممكنة حاليًا. على سبيل المثال ، إذا لم تكن هناك أية إلتزامات حتى الآن ، فمن الواضح أنه لا يمكنك الإلغاء أو الإعادة. قد يرغب مطور يستخدم هذا البرنامج المساعد في تنفيذ وظائف مماثلة.


لتمكين هذا ، يمكن أن يوفر المكوّن الإضافي خاصيتين canUndo ، canUndo و canRedo كجزء من واجهة برمجة التطبيقات العامة. هذا تافه لتنفيذ:


 module.exports = { install(Vue) { Vue.mixin({ data() { ... }, created() { ... }, methods: { ... }, computed: {}, computed: { canRedo() { return this.undone.length; }, canUndo() { return this.done.length; } }, }); }, } 

Source: https://habr.com/ru/post/ar433986/


All Articles