كيفية تمرير البيانات بين المكونات في Vue.js

نشرت: 2022-03-10
ملخص سريع ↬ مع وجود العديد من الطرق المختلفة لمشاركة البيانات عبر المكونات ، يجب أن تعرف الأسلوب الأفضل لموقفك. دعنا نحلل ثلاث من أكثر الطرق شيوعًا لتمرير البيانات في VueJS.

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

ما لم تكن تقوم بإنشاء تطبيق Vue بالكامل في مكون واحد (وهو ما لن يكون له أي معنى) ، فستواجه مواقف تحتاج فيها إلى مشاركة البيانات بين المكونات.

بنهاية هذا البرنامج التعليمي ، ستعرف ثلاث طرق لإنجاز ذلك.

  • استخدام الدعائم لمشاركة البيانات من الوالد إلى الطفل ،
  • إصدار أحداث مخصصة لمشاركة البيانات من الطفل إلى الوالد ،
  • استخدام Vuex لإنشاء حالة مشتركة على مستوى التطبيق.

حسنًا - دعنا ندخله مباشرة!

إنشاء تطبيق باستخدام Nuxt

باستخدام Spotify ، يمكن لأصدقائك التحقق مما تريد التشويش عليه. ماذا لو كان بإمكان بقية الإنترنت تجربة إيقاعك أيضًا؟ تعرف على كيفية إنشاء تطبيقك الخاص لمشاركة ما تستمع إليه على Spotify باستخدام Vue.js و Nuxt. اقرأ مقالًا ذا صلة ←

المزيد بعد القفز! أكمل القراءة أدناه ↓

1. استخدام الدعائم لمشاركة البيانات من الوالد إلى الطفل

تعتبر أدوات VueJS هي أبسط طريقة لمشاركة البيانات بين المكونات. الدعائم هي سمات مخصصة يمكننا منحها للمكون. بعد ذلك ، في نموذجنا ، يمكننا إعطاء قيم السمات هذه و - BAM - نقوم بنقل البيانات من أحد الوالدين إلى مكون فرعي!

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

  1. المكون الفرعي الذي يقبل الخاصية ، فلنسمي هذا AccountInfo.vue .
  2. المكون الرئيسي الذي يمرر الخاصية ، دعنا نسمي ProfilePage.vue .

داخل AccountInfo.vue ، يمكننا التصريح عن العناصر التي تقبلها باستخدام خيار props. لذا ، داخل خيارات المكونات ، دعنا نجعلها تبدو كما يلي.

 // AccountInfo.vue <template> <div id='account-info'> {{username}} </div> </template> <script> export default { props: ['username'] } </script>

بعد ذلك ، لتمرير البيانات من الأصل ( ProfilePage.vue ) ، نقوم بتمريرها كسمة مخصصة.

 // ProfilePage.vue <account-info username='matt' />

الآن إذا قمنا بتحميل صفحتنا ، يمكننا أن نرى أن مكون AccountInfo بنا يعرض القيمة التي تم تمريرها من قبل الأصل بشكل صحيح.

كما هو الحال عند العمل مع توجيهات VueJS الأخرى ، يمكننا استخدام v-bind لتمرير الدعائم ديناميكيًا. على سبيل المثال ، لنفترض أننا نريد تعيين خاصية اسم المستخدم لتكون مساوية لمتغير. يمكننا تحقيق ذلك باستخدام الاختصار للتوجيه v-bind (أو فقط : للاختصار). سيبدو الرمز قليلاً مثل هذا:

 <template> <div> <account-info :username="user.username" /> </div> </template> <script> import AccountInfo from "@/components/AccountInfo.vue"; export default { components: { AccountInfo }, data() { return { user: { username: 'matt' } } } } </script>

هذا يعني أنه يمكننا تغيير بياناتنا وسيتم أيضًا تحديث أي أدوات تابعة تستخدم هذه القيمة.

نصيحة: تحقق دائمًا من الدعائم الخاصة بك

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

لنفترض أننا نريد أن يقبل اسم المستخدم الخاص بنا السلاسل فقط. سيتعين علينا تعديل كائن الدعائم ليبدو كما يلي:

 export default { props: { username: String } }

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

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

نصيحة: اتبع اصطلاحات تسمية العناصر

وفقًا لدليل نمط VueJS ، فإن أفضل طريقة لتسمية الدعائم الخاصة بك هي باستخدام camelCase عند التصريح عنها في البرنامج النصي وحالة الكباب عند الرجوع إليها في كود القالب.

المنطق وراء هذا في الواقع بسيط للغاية. في Javascript ، تعد camelCase هي اصطلاح التسمية القياسي وفي HTML ، إنها حالة كباب.

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

 // GOOD <account-info :my-username="user.username" /> props: { myUsername: String } // BAD <account-info :myUsername="user.username" /> props: { "my-username": String }

2. إصدار أحداث لمشاركة البيانات من طفل إلى آخر

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

يمكن لكل مثيل Vue استدعاء طريقة .$emit(eventName) التي تقوم بتشغيل حدث. بعد ذلك ، يمكننا الاستماع إلى هذا الحدث بنفس الطريقة مثل أي حدث آخر ، باستخدام التوجيه v-on.

إنشاء حدث مخصص

دعونا نبني على مثال ملف تعريف المستخدم الخاص بنا عن طريق إضافة زر يغير اسم المستخدم. داخل المكون الفرعي الخاص بنا ( AccountInfo.vue ) ، دعنا ننشئ الزر.

بعد ذلك ، عند النقر فوق هذا الزر ، سنرسل حدثًا يسمى changeUsername .

 <template> <div id='account-info'> <button @click='changeUsername()'>Change Username</button> {{username}} </div> </template> <script> export default { props: { username: String }, methods: { changeUsername() { this.$emit('changeUsername') } } } </script>

داخل الوالد ، نتعامل مع هذا الحدث ونغير المتغير user.username . كما ناقشنا سابقًا ، يمكننا الاستماع إلى الأحداث باستخدام التوجيه v-on أو الاختصار "@".

 <template> <div> <account-info :username="user.username" @changeUsername="user.username = 'new name'"/> </div> </template>

لنجربها. يجب أن ترى أنه عند النقر فوق الزر ، يتغير اسم المستخدم إلى "اسم جديد".

نصيحة: يمكن أن تقبل الأحداث المخصصة الوسيطات

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

ومع ذلك ، لحسن الحظ ، يمكننا استخدام وسيطات المرور مع أحداثنا المخصصة لتغيير قيم المكون الرئيسي.

لنفترض أننا نريد تعديل حدث changeUsername حتى نتمكن من تمرير قيمة له.

يأخذ $emit معاملًا ثانيًا اختياريًا للوسيطات. لذلك كل ما نقوم به هو إضافة قيمة اسم المستخدم الجديد بعد اسم الحدث الخاص بنا.

 this.$emit('changeUsername', 'mattmaribojoc')

بعد ذلك ، في المكون الرئيسي الخاص بنا ، يمكننا إما الوصول إلى هذه القيم مضمنة باستخدام متغير $event خاص ، أو يمكننا كتابة طريقة معالج تأخذ معلمة.

 <account-info :username="user.username" @changeUsername="user.username = $event"/> OR <account-info :username="user.username" @changeUsername="changeUsername($event)"/> export default { ... methods: { changeUsername (username) { this.user.username = username; } } }

3. استخدام Vuex لإنشاء حالة مشتركة على مستوى التطبيق

حسنًا - نعرف كيفية مشاركة البيانات بين الآباء / الأطفال ، ولكن ماذا عن المكونات الأخرى؟ هل يتعين علينا إنشاء نظام هرمي معقد للغاية إذا أردنا تمرير البيانات؟

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

في الأساليب التي استخدمناها سابقًا (الدعائم / الأحداث المنبعثة) ، يكون لكل مكون حالة بياناته الخاصة التي نشاركها بعد ذلك بين المكونات. ومع ذلك ، يتيح لنا Vuex استخراج جميع البيانات المشتركة في حالة واحدة يمكن لكل مكون الوصول إليها بسهولة. هذه الحالة المشتركة تسمى متجر.

لنجربها.

نظرًا لأن Vuex منفصل عن الكود الأساسي لـ Vue ، فسيتعين علينا أولاً تثبيته واستيراده في مشروعنا. أولاً ، سيتعين علينا تشغيل npm install vuex --save داخل مشروعنا CLI.

بعد ذلك ، قم بإنشاء مجلد src / store بملف index.js يحتوي على الكود التالي.

 // store/index.js import Vue from "vue"; import Vuex from "vuex"; Vue.use(Vuex); export default new Vuex.Store({ state: {}, getters: {}, mutations: {}, actions: {} });

لتضمين هذا في مثيل root Vue الخاص بنا ، يتعين علينا استيراد ملف store / index.js الخاص بنا وتمريره في مُنشئ Vue الخاص بنا.

 // main.js import store from "./store"; new Vue({ store, ...

الوصول إلى Vue Store داخل المكونات

نظرًا لأننا أضفنا متجر Vuex الخاص بنا إلى مثيل الجذر Vue ، يتم حقنه في جميع أطفال الجذر. إذا أردنا الوصول إلى المتجر من أحد المكونات ، فيمكننا عبر this.$store .

الآن ، دعنا نتعمق في تفاصيل كل جزء من الأجزاء الأربعة لمتجر Vuec.

1. الدولة

حالة Vuex هي كائن يحتوي على بيانات على مستوى التطبيق. ستتمكن جميع مثيلات Vue من الوصول إلى هذه البيانات.

بالنسبة لمتجرنا ، دعنا ننشئ كائن مستخدم يخزن المزيد من بيانات ملف تعريف المستخدم.

 export default new Vuex.Store({ state: { user: { username: 'matt', fullName: 'Matt Maribojoc' } }, getters: {}, mutations: {}, actions: {} });

يمكننا الوصول إلى هذه البيانات داخل أي مكون مثيل مثل هذا.

 mounted () { console.log(this.$store.state.user.username); },

2. حاصل

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

بناءً على متجرنا السابق ، لنفترض أننا نريد إنشاء طريقة تُرجع الاسم الأول للمستخدم بناءً على سمة الاسم الكامل.

 getters: { firstName: state => { return state.user.fullName.split(' ')[0] } }

تتوفر خصائص Vuex getter للمكونات الموجودة في كائن store.getters .

 mounted () { console.log(this.$store.getters.firstName); }

نصيحة: تعرف على وسيطات Getter الافتراضية

بشكل افتراضي ، تقبل حروف Vuex وسيطتين.

  1. الدولة - كائن الدولة لطلبنا ؛
  2. getters - الكائن store.getters ، مما يعني أنه يمكننا الاتصال بأحرف أخرى في متجرنا.

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

دعنا نصنع اسمًا أخيرًا يزيل ببساطة قيمة الاسم الأول من خاصية حالة الاسم الكامل. قد يتطلب هذا المثال كلاً من الحالة وكائنات الاستلام.

 lastName (state, getters) { return state.user.fullName.replace(getters.firstName, ''); }

نصيحة: قم بتمرير الوسيطات المخصصة إلى Vuex Getters

ميزة أخرى رائعة للأحرف هي أنه يمكننا تمرير الحجج المخصصة لهم عن طريق جعل دالة getter الخاصة بنا ترجع طريقة.

 prefixedName: (state, getters) => (prefix) => { return prefix + getters.lastName; } // in our component console.log(this.$store.getters.prefixedName("Mr."));

3. الطفرات

الطفرات هي الطريقة الوحيدة لتغيير قيمة كائن الحالة بشكل صحيح. من التفاصيل المهمة التي يجب ملاحظتها أن الطفرات يجب أن تكون متزامنة .

مثل الحاصل ، تقبل الطفرات دائمًا خاصية Vuex الحكومية كحجة أولى. يقبلون أيضًا وسيطة مخصصة - تسمى الحمولة - كوسيطة ثانية.

على سبيل المثال ، لنقم بإجراء طفرة لتغيير اسم المستخدم إلى قيمة معينة.

 mutations: { changeName (state, payload) { state.user.fullName = payload } },

بعد ذلك ، يمكننا استدعاء هذه الطريقة من المكون الخاص بنا باستخدام طريقة store.commit ، حيث تكون الحمولة هي الوسيطة الثانية.

 this.$store.commit("changeName", "New Name");

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

 changeName (state, payload) { state.user.fullName = payload.newName }

هناك طريقتان مختلفتان لاستدعاء الطفرات مع الحمولة.

  1. يمكن أن يكون نوع الطفرة هو الوسيطة الأولى والحمولة كالوسيطة الثانية.
  2. يمكنك التصريح عن تمرير كائن واحد ، مع خاصية واحدة للنوع وأخرى للحمولة.
 this.$store.commit("changeName", { newName: "New Name 1", }); // or this.$store.commit({ type: "changeName", newName: "New Name 2" });

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

4. الإجراءات

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

أيضًا ، بينما يجب أن تكون طفرات Vuex متزامنة ، فإن الإجراءات لا تفعل ذلك. باستخدام الإجراءات ، يمكننا استدعاء طفرة بعد استدعاء API ، على سبيل المثال.

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

فيما يلي مثال على إجراء Vuex الذي ينتظر ثانيتين ثم يقوم بتنفيذ طفرة changeName .

 actions: { changeName (context, payload) { setTimeout(() => { context.commit("changeName", payload); }, 2000); } }

داخل مكوناتنا ، نستخدم طريقة store.dispatch من أجل تشغيل وظيفتنا. نجتاز الحجج مثلما فعلنا مع الطفرات. نعلن عن النوع ونمرر أي وسيطات مخصصة في الوسيطة الثانية.

 this.$store.dispatch("changeName", { newName: "New Name from Action" });

تغليف

الآن ، يجب أن تعرف ثلاث طرق مختلفة لمشاركة البيانات عبر المكونات في VueJS: الدعائم والأحداث المخصصة ومتجر Vuex.

آمل أن يساعدك هذا البرنامج التعليمي في إعطائك مزيدًا من الأفكار حول بعض أساليب Vue وأفضل الممارسات المختلفة. اسمحوا لي أن أعرف كيف قمت بتنفيذها في مشاريعك!

قراءة متعمقة

إذا كنت مهتمًا بالتعمق أكثر في الجانب / القدرات التقنية لكل تقنية ، فإليك بعض الأماكن الرائعة للبدء.

  • موقع Vuex Official Guide
  • مستندات VueJS للدعامات والأحداث المخصصة
  • “WTF هل Vuex؟ دليل المبتدئين إلى متجر بيانات تطبيق Vue ، "أنتوني جور ، Vue.js Developers