Vue: انتظار خطافات دورة حياة المكون غير المتزامن

تم إنشاؤها على ٨ ديسمبر ٢٠١٧  ·  51تعليقات  ·  مصدر: vuejs/vue

ما المشكلة التي تحلها هذه الميزة؟

إذا احتاج المستخدم إلى تنفيذ خطاف دورة حياة يعتمد على عمليات غير متزامنة ، فيجب أن تحترم vue الطبيعة غير المتزامنة للخطاف المنفذ وتنتظره في vue land.

كيف تبدو واجهة برمجة التطبيقات المقترحة؟

API لا يتغير. فقط كيف يعمل الآن من خلال انتظار الخطافات غير المتزامنة.

التعليق الأكثر فائدة

هذا هو الكود الفعلي الذي أريد أن أكون بانتظاره:

  beforeMount: async function() {
       this.user = await client.get({type: 'user', id: this.$route.params.id});
    }

والذي سيكون جزءًا من المكون UserPage .

ال 51 كومينتر

لذلك تريد

created () {
    return new Promise(resolve => {
        setTimeout(() => {
            console.log('created')
            resolve()
        })
    })
},
mounted () {
    console.log('mounted')
}

لعرضهم

mounted

؟

عند إنشاء طلب ميزة ، يرجى إضافة حالة استخدام واقعية لجعل الطلب يستحق التنفيذ.

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

يتم الإغلاق في الوقت الحالي ، ولكن لا تتردد في المتابعة بمزيد من المنطق / حالات الاستخدام / الآثار الملموسة.

posva مفهوم - أعتذر. حالة الاستخدام الفعلي الخاصة بي هي حالة لديّ فيها مكون UserPage يتلقى user_id من معلمات مسار الصفحة (من خلال this.$route.params ) ، ثم جلب بيانات المستخدم الفعلية من قاعدة البيانات على الخادم باستخدام أمر مثل:
this.user = await client.get({type: 'user', id: this.$route.params.id})
حيث يشير this.user إلى حقل user في الجزء data من المكوّن UserPage .

من الناحية المثالية ، أريد أن يتم تنفيذ هذا السطر من التعليمات البرمجية بعد إنشاء المكون (بحيث يكون this.$route.params متاحًا) ولكن قبل تثبيت المكون فعليًا بحيث يمكنني استخدام user بأمان في القالب الخاص بي استيفاء

@ yyx990803
قد أكون مستجدًا هنا ، لكن ألا يجب أن يكون التغيير الوحيد هو إضافة الكلمة الرئيسية await قبل استدعاء خطافات دورة الحياة مثل mounted ، إلخ ، في Vue land؟

هذا هو الكود الفعلي الذي أريد أن أكون بانتظاره:

  beforeMount: async function() {
       this.user = await client.get({type: 'user', id: this.$route.params.id});
    }

والذي سيكون جزءًا من المكون UserPage .

لا داعى للقلق! كنت أتخيل حالة الاستخدام هذه. من الأفضل التعامل معه كما هو موضح في مستندات vue-router لأنه يفتح طرقًا مختلفة لعرض حالة التحميل. يمكنك بالفعل الانتظار حتى تكون البيانات موجودة قبل عرض المكون راجع للشغل.

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

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

لديك طرق عديدة للقيام بذلك. أبسطها هو استخدام متغير يبدأ فارغًا ، وجلب البيانات وتعيينها ، وتبديل المكون الفعلي (بسبب v-if). قد يكون الإصدار الأكثر غرابة هو الوظيفة التي تعمل على حل المكون واستخدام <component :is="myDynamicComp"/> 😄
لكن من فضلك ، لا تختطف المشكلة في سؤال استخدم المنتدى أو الخلاف لذلك

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

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

لدي بعض حالات الاستخدام هنا وأود الحصول على بعض الاقتراحات وطريقة الحل.

MainPage.vue هي الحاوية الرئيسية الخاصة بي. اتصل بـ ajax "/ init" على beforeCreate للحصول على معلومات المستخدم ثم الالتزام بـ Vuex.store.
Content.vue هو الطفل داخل MainPage.vue . أرغب في الاتصال بمكالمات مختلفة لواجهة برمجة التطبيقات على مستوى mounted وفقًا لدور المستخدم الذي يأتي من Vuex.store.

إذا كانت مكالمة دورة الحياة في تدفق غير متزامن / انتظار ، فسيتبع الأمر
الأصل قبل الإنشاء -> إنشاء الأصل -> الطفل قبل الإنشاء -> إنشاء الطفل -> تم تثبيت الطفل ... (إذا فهمت بشكل صحيح دورة حياة المكون).

لكن لا يمكنني حاليًا الحصول على معلومات المستخدم على Content.vue ، كيف يمكنني الحصول على حل بديل الآن؟
أرغب في الاحتفاظ بواجهة برمجة تطبيقات "/ init" تسمى بداخل MainPage.vue لأنها تُستخدم في العديد من الصفحات (الحاوية في Vue-Router).

السؤال المنشور على stackoverflow

شكرا

حل بديل لما يستحق:

{
  created: function(){
    this.waitData = asyncCall();
  },
  mounted: function(){
    this.waitData.then(function(data) { ... })
  }
}


حل ممكن أكثر "مسطحة":

{
    async created () {
        let createdResolve = null
        let createdReject = null
        this.createdPromise = new Promise(function(resolve, reject){
            createdResolve = resolve
            createdReject = reject
        })
        await asyncCall1()
        await asyncCall2()
        ...
        createdResolve(someResult)
    }
    async mounted () {
        let result = await this.createdPromise
        ...
    }
    data () {
        return {
            createdPromise: null
        }
    }
}

أليس هذا شيء بعد؟

data() {
 ...
},
async created() {
  const something = await exampleMethod();
  console.log(something);
}

يعمل من أجلي (كما يذكر fifman ).

breadadams نعم ، بالطبع. سيتم انتظار الدالات _inside_ طريقة created - لكن الوظيفة created أو mounted نفسها ليست كذلك.

لذا فإن مثيل Vue سوف يستدعي created وعلى الفور mounted قبل الانتهاء من أي من العمليات طويلة الأمد في created

آه ، darren-dev الخاص بي - حالة استخدام مختلفة من جانبي ، لكني أرى المشكلة الآن 😅 شكرًا للتوضيح.

breadadams لا توجد مشكلة على الإطلاق - نحن جميعًا هنا من أجل

يمكن أن يكون خطاف دورة الحياة غير المتزامن تنفيذًا جيدًا في الإصدار الرئيسي التالي

يبدو لي أن السماح بالدعم غير المتزامن لأساليب دورة الحياة سيشجع ممارسات UX السيئة افتراضيًا. كيف؟ يتم استخدام الوظائف غير المتزامنة للطلبات التي لا يمكن إكمالها على الفور (على سبيل المثال ، طلبات التشغيل أو طلبات الشبكة). إن إجبار Vue على تأخير الإنشاء أو التثبيت أو أي من طرق دورة الحياة الأخرى للانتظار عند طلب الشبكة أو العملية غير المتزامنة طويلة الأمد سيؤثر على المستخدم بطرق ملحوظة. تخيل أن مستخدمًا قادمًا إلى موقعك ثم اضطر إلى الانتظار لمدة 4 ثوانٍ مع شاشة فارغة أثناء انتظار المكون للاتصال الخلوي المتقطع للمستخدم لإنهاء طلب الشبكة. ولا يؤثر ذلك سلبًا على المستخدم فحسب ، بل إنك تضحي أيضًا بتحكمك في الموقف - لا يوجد شيء يمكنك القيام به كمطور لجعل المستخدمين يدركون وقت التحميل بشكل أسرع ، أو إظهار مؤشرات تقدم محددة أو غير محددة. لذلك من خلال بناء هذه القدرة في Vue ، فإنك لا تجعل الويب مكانًا أفضل ؛ أنت تمكّن الممارسات السيئة.

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

seanfisher أنت تطرح نقطة صحيحة. من الناحية المعمارية ، يجب أن يتعامل المطور مع التصميم حول مجموعة أحداث غير متزامنة - لأن هذه هي الطريقة الوحيدة لتصوير الرسالة بشكل صحيح.

إخلاء المسؤولية : تمت كتابة ما يلي مع وضع فكرة إنشاء الصفحة في الاعتبار. هناك بالتأكيد حالات استخدام صالحة حيث تكون حجتي غير صالحة.


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

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

تذكر ، حجتي هي أن Vue لا ينبغي أن تخبرني أن تطوير Im بشكل خاطئ. يجب أن توفر الوظيفة المطلوبة فقط.

ومع ذلك ، لا ينبغي ترك إملاء أنماط التصميم الخاصة بالمطور متروكًا لإطار العمل الذي تستخدمه.

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

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

سكوت

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

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

لن أزعم أبدًا أن إطار العمل المصمم جيدًا يجب أن يمتد بنفس نمط التصميم ، لكن حجتي هي أن الإطار لا يمكن أن يمليه.

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

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

سكوت

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

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

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

للرأي القائل بأنه من الممارسات السيئة أن تجعل المستخدم ينتظر عدم التزامن الذي تم إنشاؤه أو ربط دورة حياة أخرى بدون مؤشر على حدوث شيء ما ،

هل هذه حقا مشكلة؟

سكوت

هذه هي المشكلة التي أواجهها - وربما يمكن لشخص ما أن يقترح كيف أفعل ذلك لأن هذا يبدو إشكاليًا.

تطبيق Vue الخاص بنا (كبير نوعًا ما) يستخدم Vuex على نطاق واسع. في عدد قليل جدًا من مكونات Vue الخاصة بنا في دورة حياة create () قمنا بتعيينها عبر store.dispatch () بعض العناصر في المتجر (من الواضح). ومع ذلك ، كما لفت انتباهي - store.dispatch () دائمًا ما يُعيد وعدًا .. حتى لو كان المنطق الأساسي والوظيفة غير متزامنين. لذلك وضعت في وضع غير متزامن () {await store.dispatch ('foo / action')} ولكن كما لوحظ أنه فشل في الواقع ..

أنا أستخدم أيضًا Typescript وهي تشتكي بمرارة عندما لا أنتظر /.

إذن ما هي أفضل طريقة لاستخدام Vuex store.dispatch () في دورة الحياة عندما لا يمكننا فصلها؟

هتافات!!

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

أنا أنظر إلى حلfifman "الأكثر mounted() . في هذا الحل ، يكون كلا من created() و mounted() غير متزامن ، لذلك سوف يتصل Vue بكل منهما وسيعود أكثر أو أقل فورًا ، مع استمرار وجود العناصر غير المتزامنة في الخلفية. في الواقع ، لست متأكدًا من أن هذا أفضل من مجرد التخلص من createdPromise والقيام بكل الأعمال غير المتزامنة إما في created() أو mounted() ، مثل:

async mounted() {
  let response = await fetch(my_url)
  let data = await response.text()
  my_data_member = data
}

على أي حال ، سيتم ملء my_data_member "لاحقًا" عند اكتمال XHR ، بعد فترة طويلة من إرجاع mounted() وعدها ، أليس كذلك؟

يمكنك أيضًا محاولة استخدام v-if على مكون الجذر <div id="app"/> وتشغيله عند انتهاء تحميل البيانات. أنا ، على سبيل المثال ، استخدمه لتحديث الرمز المميز.

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

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

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

+1 لهذه الميزة.
لدي مزيج تستخدمه مكونات مختلفة ، يقوم mixin بجلب البيانات من قاعدة بيانات في الخطاف المركب.
يجب أن تعمل المكونات مع البيانات التي يتم جلبها بواسطة mixin أيضًا في الخطاف المركب.
كما هو الحال الآن ، اضطررت إلى تنفيذ رد اتصال ليتم استدعاؤه عندما ينتهي mixin من تحميل البيانات والتخلص من الخطاف المركب في المكون.
إنه يعمل ولكن سيكون أجمل إذا تعامل الخطاف المركب مع الوعود.

cederron بدافع الاهتمام تمامًا ، لماذا لا يمكنك تنزيل البيانات في المكون الرئيسي وتمريرها كعنصر أساسي؟ استخدم v-if لإظهار مؤشر التحميل أثناء تحميل البيانات وعندما تظهر البيانات ، يمكنك إظهار المكون ، وعندما يتم إنشاؤه ، سيكون لديه جميع البيانات التي يحتاجها.

يتم تجنب وجود المكون الذي يمثل حالتين مميزتين غير مرتبطين ("لا توجد بيانات محملة ، في انتظار" و "تم تحميل البيانات ، يمكنك معالجتها")

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

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

AFAIK هذا لن يعمل:

export const MyMixin = {
    data: function () {
        return {
            dbData: null
        }
    },
   mounted:  async function () {
      this.dbData = await asyncFetchDataFromDB()
   }
}


export const MyComponent = {
    mixins: [MyMixin],
    data: function () {
        return {
            newData: null
        }
    },
   mounted:  function () {
      this.newData = handleDBData(this.dbData)
   }
}

ستكون dbData خالية في ربط تحميل المكون.

أقوم حاليًا بتنفيذ رد اتصال عندما يقوم mixin بجلب البيانات ولكن سيكون من الأجمل فقط جعل وظيفة التحميل غير متزامنة.

لا أستطيع أن أقول الكثير عن vuex لأنني لا أستخدمها

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

لكنني سأشعر بخيبة أمل حقًا لإعادة كتابة كل خطاف في دورة حياتي لتجنب حظر vue ، فإن async/await أنظف كثيرًا ، لذلك نحن لا نستخدم الوعود. يؤدي تغيير هذا بطريقة غير متوافقة مع الإصدارات السابقة إلى تغيير نقطة النجاح (دورة حياة المكون غير المتوقع) إلى حفرة من الفشل.

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

seanfisher شكرا لك ، هذا مفيد للغاية!

لماذا لا تستخدم مكونًا غير متزامن بدلاً من ذلك ، والذي سيتم عرضه فقط عند عودة المكالمات غير المتزامنة؟
مزيد من المعلومات حول API هنا
https://vuejs.org/v2/guide/components-dynamic-async.html#Async -Components

new Vue({
  components: {
    root: () => ({ // Aync component
      // The component to load (should be a Promise)
      component: new Promise(async function (resolve) {
        await FetchMyVariables()
        resolve(MyComponent) // MyComponent will be rendered only when FetchMyVariables has returned
      }),
      // A component to use while the async component is loading
      loading: { render: (h) => h('div', 'loading') }, 
    })
  },
  render: h => h('root')
})

بينما تبدو معظم هذه الحلول جيدة ، أعتقد أن هذه واحدة من تلك الأجزاء الرئيسية المفقودة من Vue والتي تجعلها بديهية للغاية. أعتقد أن Vue 3 يحتاج إلى تنفيذ هذا لأننا وصلنا إلى النقطة التي أصبح فيها استخدام الانتظار غير المتزامن أمرًا يوميًا. لذا يرجى @ yyx990803 أنت ، دعونا نحصل عليها في Vue 3. PLEEEEEASE. تم إنشاء بنية VUE بالكامل دون افتراض هذه الحالات ومعظم الأشياء التي ينشرها الأشخاص هنا هي مجرد حلول بديلة ومخترقة. أعتقد أن الخطافات يجب أن تحترم في الواقع الوظائف غير المتزامنة وتتوقع أيضًا قيم إرجاع أيضًا يتم تمريرها بعد ذلك إلى وظيفة الخطاف التالية.

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

يبدو لي أن السماح بالدعم غير المتزامن لأساليب دورة الحياة سيشجع ممارسات UX السيئة افتراضيًا. كيف؟ يتم استخدام الوظائف غير المتزامنة للطلبات التي لا يمكن إكمالها على الفور (على سبيل المثال ، طلبات التشغيل أو طلبات الشبكة). إن إجبار Vue على تأخير الإنشاء أو التثبيت أو أي من طرق دورة الحياة الأخرى للانتظار عند طلب الشبكة أو العملية غير المتزامنة طويلة الأمد سيؤثر على المستخدم بطرق ملحوظة. تخيل أن مستخدمًا قادمًا إلى موقعك ثم اضطر إلى الانتظار لمدة 4 ثوانٍ مع شاشة فارغة أثناء انتظار المكون للاتصال الخلوي المتقطع للمستخدم لإنهاء طلب الشبكة. ولا يؤثر ذلك سلبًا على المستخدم فحسب ، بل إنك تضحي أيضًا بتحكمك في الموقف - لا يوجد شيء يمكنك القيام به كمطور لجعل المستخدمين يدركون وقت التحميل بشكل أسرع ، أو إظهار مؤشرات تقدم محددة أو غير محددة. لذلك من خلال بناء هذه القدرة في Vue ، فإنك لا تجعل الويب مكانًا أفضل ؛ أنت تمكّن الممارسات السيئة.

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

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

إذا قاتل إطار عمل المطور ، فسيجد المطور إطارًا آخر.

@ robob4him

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

إذا قاتل إطار عمل المطور ، فسيجد المطور إطارًا آخر

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

wparad ، إنه

نصف ميزات أي إطار / لغة حرفيًا تشكل خطرًا على المطور ؛ يمكن توسيع الطرق العامة ، ويشجع Vue الوصول إلى العنصر ($ el) ، وما إلى ذلك. توفر الأطر هذه الأشياء لأنه في نهاية اليوم يحتاج المطور إلى إنجاز المهمة.

طلب الميزة هذا عمره عام. يجب أن يفهم الناس أن السبب في الواقع ليس لأنه قد يتسبب في ممارسات سيئة ولا يجب أن يروا أن التأخير في التقديم هو ممارسة سيئة.

أحتاج إلى استخدام needjs مع vue. لا يعجبني needjs ولكن لأنني أرغب في استخدام vue مع نظام LMS مفتوح المصدر يحتوي على جميع وحداته كوحدات AMD. سيكون من الرائع أن أتمكن من تحميل جميع libs التي أحتاجها في الخطاف السابق. البديل بالنسبة لي في الوقت الحالي هو تحميلهم خارج vue ثم تمريرهم في أي مكان أكثر فوضوية.

يبدو لي أن السماح بالدعم غير المتزامن لأساليب دورة الحياة سيشجع ممارسات UX السيئة افتراضيًا. كيف؟ يتم استخدام الوظائف غير المتزامنة للطلبات التي لا يمكن إكمالها على الفور (على سبيل المثال ، طلبات التشغيل أو طلبات الشبكة). إن إجبار Vue على تأخير الإنشاء أو التثبيت أو أي من طرق دورة الحياة الأخرى للانتظار عند طلب الشبكة أو العملية غير المتزامنة طويلة الأمد سيؤثر على المستخدم بطرق ملحوظة. تخيل أن مستخدمًا قادمًا إلى موقعك ثم اضطر إلى الانتظار لمدة 4 ثوانٍ مع شاشة فارغة أثناء انتظار المكون للاتصال الخلوي المتقطع للمستخدم لإنهاء طلب الشبكة. ولا يؤثر ذلك سلبًا على المستخدم فحسب ، بل إنك تضحي أيضًا بتحكمك في الموقف - لا يوجد شيء يمكنك القيام به كمطور لجعل المستخدمين يدركون وقت التحميل بشكل أسرع ، أو إظهار مؤشرات تقدم محددة أو غير محددة. لذلك من خلال بناء هذه القدرة في Vue ، فإنك لا تجعل الويب مكانًا أفضل ؛ أنت تمكّن الممارسات السيئة.

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

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

أعتقد أنك تتجاهل حقيقة أن معظم حالات الاستخدام قد لا تكون حتى بصفحة فارغة. يطلق عليهم مكونات لسبب. الحالات التي أرغب فيها شخصيًا في استخدام هذا هو المكان الذي يوجد فيه شيء ما بالفعل على الشاشة يفعل شيئًا آخر. ربما تم حظر هذا المكون بواسطة v-if على سبيل المثال ويتم تشغيله عندما يتغير شيء ما. ومع ذلك ، في عملية تصييرها لأول مرة ، يجب احترام async functions وما إلى ذلك أثناء تشغيل المكون. لقد قمت برعاية وثائق Vue بأكملها بحثًا عن هذا ، وأخيراً قمت بذلك بحل بديل غير جميل مثل الأمثلة الاختراق أعلاه.

ما يقلقني هو شخص ما / حتى لاحقًا أنا احتفظ بالشفرة. إنه مثل الوعد مقابل الجحيم مقابل Async ... انتظر.

في الواقع ، أرى أنه يعزز مرونة إطار العمل وإمكانية التحكم فيه بطريقة سهلة للمتابعة. ما عليك سوى إلقاء نظرة على الاختراقات أعلاه لمعرفة ما أعنيه. يقوم المطورون بكل ذلك فقط لملء فجوة عبارة async mounted () { await... } على سبيل المثال. إذا كنت لا تريد استخدام هذه الميزات ، فأنت لا تحدد الوظائف على أنها async أو حتى تستخدم await على الإطلاق.

في الواقع ، من المرجح أن يفهم الشخص الذي يستخدم خطاف دورة حياة async mounted ما يفعله ولماذا يفعل ذلك ، وعلى الأرجح لن يقوم بهذه الممارسات السيئة التي تقلقك.

emahuni ، لا أعتقد أن أي شخص قد يختلف مع التوقعات التي تشاركها ، لكنني أعتقد أن هناك async mounted أو async created يؤخر عرض المكوّن. ماذا يفعل الوالد في هذه الحالة؟ هل هو:

  • منع كذلك
  • افترض أنه من المفترض إزالة المكون v-if حتى يتم تحميله
  • افترض أن المكون من المفترض أن يكون مخفيًا حتى اكتمال التحميل
  • إظهار عنصر مؤقت في مكانه؟

بينما أوافق على أن التوقعات حول المكون الذي يتم تحميله ديناميكيًا متسقة ، فإن سلوك الوالد الذي لا أعتقد أنه سيكون كذلك. في هذه الحالات ، ستكون المنظمة البحرية الدولية (IMO) تعرض تنفيذ الطفل للوالد وتجبر الوالد على معرفة ما يجب فعله بهذا المكون الديناميكي. بدلاً من ذلك ، يجب أن تكون كيفية تحميل البيانات وحالة المكون الفرعي متروكة للطفل. إذا تم تحميل غير متزامن ، فإنه يحتاج إلى طريقة ما لشرح لـ Vue ما يجب تقديمه في مكانه (أو عدم تقديمه). أفضل طريقة للتعامل مع هذا هو كيف يعمل الإطار بالفعل ، بدلاً من تقديم تعقيد جديد.

علاوة على ذلك ، أنا لا أتابع حجتك تمامًا على الرغم من:

ما تقوله هو مثل إضافة ميزات v-if / v-clock / v-show ستشجع الممارسات السيئة لذلك نحن أفضل نخدع إطار العمل عن طريق إزالة تلك الميزات

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

emahuni ، لا أعتقد أن أي شخص قد يختلف مع التوقعات التي تشاركها ، لكنني أعتقد أن هناك async mounted أو async created يؤخر عرض المكوّن. ماذا يفعل الوالد في هذه الحالة؟ هل هو:

  • منع كذلك

يمكن للوالد أن يمضي قدماً ويقدم دون انتظار الطفل ، فلماذا؟ يمكنه المضي قدمًا وتشغيل updated بمجرد تقديم الطفل.

  • لنفترض أنه من المفترض إزالة المكون v-if حتى يتم تحميله

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

  • افترض أن المكون من المفترض أن يكون مخفيًا حتى اكتمال التحميل

هذا يعتمد على المطور ، ولماذا يقوم بفصل الخطاف المثبت أو أي خطاف آخر لهذه المسألة.

  • إظهار عنصر مؤقت في مكانه؟

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

بينما أوافق على أن التوقعات حول المكون الذي يتم تحميله ديناميكيًا متسقة ، فإن سلوك الوالد الذي لا أعتقد أنه سيكون كذلك. في هذه الحالات ، ستكون المنظمة البحرية الدولية (IMO) تعرض تنفيذ الطفل للوالد وتجبر الوالد على معرفة ما يجب فعله بهذا المكون الديناميكي. بدلاً من ذلك ، يجب أن تكون كيفية تحميل البيانات وحالة المكون الفرعي متروكة للطفل. إذا تم تحميل غير متزامن ، فإنه يحتاج إلى طريقة ما لشرح لـ Vue ما يجب تقديمه في مكانه (أو عدم تقديمه). أفضل طريقة للتعامل مع هذا هو كيف يعمل الإطار بالفعل ، بدلاً من تقديم تعقيد جديد.

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

علاوة على ذلك ، أنا لا أتابع حجتك تمامًا على الرغم من:

ما تقوله هو مثل إضافة ميزات v-if / v-clock / v-show ستشجع الممارسات السيئة لذلك نحن أفضل نخدع إطار العمل عن طريق إزالة تلك الميزات

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

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

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

سأل أحدهم هذا https://github.com/vuejs/vue/issues/7209#issuecomment -424349370 هناك ولم يرد عليه أحد بقدر ما رأيت. هذا يظهر إلى حد بعيد حقًا أن Vue تتأخر في هذا الجزء. تم تصميم هذا الجزء من الهندسة المعمارية عندما لم يكن المتزامن شيئًا بعد. لذا فإن تحديثه لتلبية المتطلبات الحديثة للهندسة المعمارية الحديثة يعد فكرة جيدة بالتأكيد. وإلا فإن الباقي هو الاختراق والحلول التي تحتاج إلى طرق محددة للقيام بذلك بدلاً من القيام بما يحدث في الصناعة.

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

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

لم أوضح هذه النقطة مطلقًا ، فأنا أرغب في تنفيذ إجراءات غير متزامنة بشكل افتراضي دون منع المكون من العرض. من غير البديهي أن يؤدي تنفيذ إجراءات async في كتلة mounted أو created إلى تأخير عرض المكون. بافتراض أن هذا هو الحال ، أود بدلاً من ذلك أن أرى التعقيد ينشأ من كيفية استمرار المستهلك الذي يريد الوظيفة الحالية. الحجة حتى الآن ليست أن ما يُطلب منك ، لا يمكن فعله ، إنه أن ما يُطلب يجب أن يكون الافتراضي. يمكنك بالفعل منع عرض المكون الخاص بك عن طريق تبديل القالب المعروض بناءً على v-if="loaded" .

يبدو الآن العرض بدون حظر الشفرة كما يلي:
هذا الرمز الآن هو:

<template>
  <div>  
    <spinner v-if="!loaded">
    <div v-else>
      ....
    </div>
</template>

<script>
  async created() { 
    await this.loadData();
    this.loaded = true;
  }
</script>

والعرض مع المنع يبدو بنفس الطريقة تمامًا ، حيث لا يمكنك منعه فعليًا. بافتراض أن async created() بحظر المكون بالفعل. ثم لدينا الآن فصل الشفرة. لعرض الدوار نكتب:

<template>
  <div>  
    <spinner v-if="!loaded">
    <div v-else>
      ....
    </div>
</template>

<script>
  created() { 
    this.loadData().then(() => this.loaded = true);
  }
</script>

وتجاهل فقط عرض المكون على الشاشة الذي نكتبه

<template>
  <div>  
    <div>
      ....
    </div>
</template>

<script>
  async created() { 
    await this.loadData();
  }
</script>

ما فائدة إضافة هذا التبسيط لحظر أمر العرض إلى جعل عدم الحظر أكثر تعقيدًا؟ أنا فقط لا أراها.

التعامل مع التبعية للمكونات

@ yyx990803 يرجى إلقاء نظرة على هذا ، إنه ليس مثاليًا ، ولكنه مع ذلك سيناريو حالة استخدام معقد.

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

أحتاج إلى المكون A لانتظار إطلاق خطافات مكون B && C mounted قبل تركيب نفسه. لذا يجب أن ينتظر المكون A mounted خطافه created ، مما أدى إلى تثبيت المكون B & C الذي كان ينتظر المشغل _ (والذي يمكنه فعل شيء قبل الانتظار) _. الشيء أسهل بهذه الطريقة وأكثر نظافة وبديهية حيث يبقى كل شيء في مكان واحد للمكون المعني.

يصدر A حدث إطلاق ويستمع إلى استجابات من B و C _ (انتظر B و C إشارة A قبل المتابعة ، ثم يرسل الأحداث بمجرد تركيبها) _ قبل المتابعة ، ببساطة. هذا يشبه إلى حد كبير سيناريو التبعية للمكونات دون أي بيانات دخيلة متناثرة في مكان آخر لإدارة الحالة.

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

<template>
  <div>
     ...
     <component-A/>
     <component-B/>
     <component-C/>
     ... other conent
  </div>
</template>
<script>
  import ComponentA...
  ...
  export default {
      components: { ComponentA... }
  }
</script>

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

<template>
  ...
</template>
<script>
  export default {
      async created() {
          // ...do something here before mounting thrusters, even await it
         this.root.$emit('mount-thrusters');
         await Promise.all([
            this.wasMounted('thruster-1-mounted'), 
            this.wasMounted('thruster-2-mounted')
         ]); 
      },
      mounted() {
        // will only run after components B and C have mounted
        ...
      },

     methods: {
       wasMounted(compEvent) {
          return new Promise( (resolve)=>this.root.$once(compEvent, ()=>resolve()));
       }
    }
  }
</script>

المكون ب

<template>
  ...
</template>
<script>
  export default {
      async created() {
          // ...do something here, even await it, but happens at the same time as all components
         await new Promise( (resolve)=>this.root.$once('mount-thrusters', ()=>resolve()));
      },
     mounted() {
       this.root.$emit('thruster-1-mounted');
    }
  }
</script>

المكون ج

<template>
  ...
</template>
<script>
  export default {
      async created() {
          // ...do something here, even await it, but happens at the same time as all components
         await new Promise( (resolve)=>this.root.$once('mount-thrusters', ()=>resolve()));
      },
     mounted() {
       this.root.$emit('thruster-2-mounted');
    }
  }
</script>

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

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

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

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

جعل الأشياء تبقى طازجة

من Coz ، لا يقتصر هذا على التركيب والتكوين فحسب ، بل يجب أن يعمل مع جميع خطافات دورة الحياة الأخرى. تخيل لو كان هذا في خطاف جديد لامع beforeActivate / beforeUpdate . يمكننا أن نجعل المكون ينتظر _تفعيل / تحديث _ وفقط _activate / update_ عندما يتم التحديث في كل مرة يتم فيها تنشيط / تحديث المكون ؛ التأكد من بقاء الأشياء جديدة.

القائمة لا حصر لها بمجرد تنفيذ هذا.

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

لم أوضح هذه النقطة مطلقًا ، فأنا أرغب في تنفيذ إجراءات غير متزامنة بشكل افتراضي دون منع المكون من العرض. من غير البديهي أن يؤدي تنفيذ إجراءات async في كتلة mounted أو created إلى تأخير عرض المكون. بافتراض أن هذا هو الحال ، أود بدلاً من ذلك أن أرى التعقيد ينشأ من كيفية استمرار المستهلك الذي يريد الوظيفة الحالية. الحجة حتى الآن ليست أن ما يُطلب منك ، لا يمكن فعله ، إنه أن ما يُطلب يجب أن يكون الافتراضي. يمكنك بالفعل منع عرض المكون الخاص بك عن طريق تبديل القالب المعروض بناءً على v-if="loaded" .

يبدو الآن العرض بدون حظر الشفرة كما يلي:
هذا الرمز الآن هو:

<template>
  <div>  
    <spinner v-if="!loaded">
    <div v-else>
      ....
    </div>
</template>

<script>
  async created() { 
    await this.loadData();
    this.loaded = true;
  }
</script>

والعرض مع المنع يبدو بنفس الطريقة تمامًا ، حيث لا يمكنك منعه فعليًا. بافتراض أن async created() بحظر المكون بالفعل. ثم لدينا الآن فصل الشفرة. لعرض الدوار نكتب:

<template>
  <div>  
    <spinner v-if="!loaded">
    <div v-else>
      ....
    </div>
</template>

<script>
  created() { 
    this.loadData().then(() => this.loaded = true);
  }
</script>

وتجاهل فقط عرض المكون على الشاشة الذي نكتبه

<template>
  <div>  
    <div>
      ....
    </div>
</template>

<script>
  async created() { 
    await this.loadData();
  }
</script>

ما فائدة إضافة هذا التبسيط لحظر أمر العرض إلى جعل عدم الحظر أكثر تعقيدًا؟ أنا فقط لا أراها.

هذا هو Vue 101 bootcamp ولا جديد هناك ... لا يكفي لتغطية الحالات المذكورة أعلاه على سبيل المثال. الفكرة هنا هي تقليل التعقيد في منطقة المستخدم حيث يتم استخدام Vue بالفعل والاستفادة بشكل أسهل من التعليمات البرمجية المنطقية.

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

أنا في حيرة من أمري بسبب هذا ، فبدلاً من اقتران B & C بـ A ، كنت سأقوم بنقل الكود إلى "تحميل A" إلى Ajs ثم أجعل A.js تُحدِّث "B.data" و "C.data" . بهذه الطريقة إذا تغيرت بيانات A. لأي سبب من الأسباب ، يتم عرض المكونات الأخرى تلقائيًا بدلاً من محاولة التفويض
السيطرة من عنصر إلى آخر. حتى في الحالة المشتركة ، ما زلت أفصل البيانات لتقديم A من المكون A. لقد استخدمنا صنفًا واحدًا يحتوي على طرق مثل hasInitialized والتي تعتبر الأخيرة وعدًا
يؤدي الاقتران المباشر بين المكونات معًا إلى إنشاء أشجار تبعية غير متوقعة تمنع إعادة استخدام المكونات وتسمح لـ vue بإعادة عرضها بشكل صحيح.

بدلاً من ذلك ، أود أن emit الحدث مباشرة إلى أصل A و B و C ، وليس على النطاق العام ، وأسمح للوالد بتحديد ما إذا كان سيتم عرض B و C ، أي

  <template>
    <a-component @rendered="showBandC = true" />
    <b-component v-if="showBandC" />
    <c-component v-if="showBandC" />
  </template>

ما هو الشيء المتعلق بـ A والذي سنحتاج في هذه الحالة إلى تقديمه قبل تصيير B و C. إذا كانت هناك أشياء في طريقة created() ، فلا شيء يمنع ذلك من ملء المتجر عبر فئة جافا سكريبت أو استخدام وحدة store . لكن حالة الاستخدام الصريح ستكون أكثر فائدة ، أي ما هي تجربة المستخدم لقصة المستخدم التي لا يمكن التقاطها؟

الفكرة هي أن تحترم Vue عدم التزامن داخليًا قبل الانتقال إلى وظيفة الخطاف التالية.

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

يحتوي المكون الخاص بي على كل من async beforeMount و async mounted ، لكن الكود الموجود في mounted يتم تنشيطه قبل اكتمال الكود في beforeMount . كيف يمكننا منع mounted من التشغيل قبل اكتمال beforeMount ؟

وهو نوع من الطلب الأصلي ، لذا أعتقد أن السؤال الذي تم طرحه في الرد الثاني لا يزال ذا صلة: https://github.com/vuejs/vue/issues/7209#issuecomment -350284784

يتم الإغلاق في الوقت الحالي ، ولكن لا تتردد في المتابعة بمزيد من المنطق / حالات الاستخدام / الآثار الملموسة.

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

أي ما يحدث عندما تحاول unmount مكون لم ينته بعد created ، واو ، سيكون من السيئ أن تنتظر ذلك. أو destroying الواحد الذي لم ينته من كونه mounted ، لا أحسد المنفذ لهذه الوظيفة.

أنا في حيرة من أمري بسبب هذا ، فبدلاً من اقتران B & C بـ A ، كنت سأقوم بنقل الكود إلى "تحميل A" إلى Ajs ثم أجعل A.js تُحدِّث "B.data" و "C.data" . بهذه الطريقة إذا تغيرت بيانات A. لأي سبب من الأسباب ، يتم عرض المكونات الأخرى تلقائيًا بدلاً من محاولة التفويض

هذا التعقيد زاد ، الممارسة السيئة. جرب كتابته هنا بالكامل ، دعنا نرى ما تعنيه ، لكن بالنسبة لي لقد زادت التعقيد كثيرًا.

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

هذا الآن يقترن المكونات كثيرًا. نريد أن يعمل هؤلاء دون الآخر باستثناء A.

يؤدي الاقتران المباشر بين المكونات معًا إلى إنشاء أشجار تبعية غير متوقعة تمنع إعادة استخدام المكونات وتسمح لـ vue بإعادة عرضها بشكل صحيح.

في الحقيقة أنت تفتقد النقطة ، فهذه مرتبطة بشكل فضفاض بالتمديد الذي يمكن استخدام كل منها وصيانته دون التأثير على الآخر. في الواقع ، يمكنك إسقاط أي منها عدة مرات في أي مكان دون كتابة أي رمز آخر في الوالدين خارج <component-x /> ، لا يوجد v-if ، vuex لإدارة حالتها أو أي شيء آخر.

لقد قمت بربطهم من A إلى B و C فقط للتوضيح ، كان بإمكاني تقسيم هذا بشكل جيد أو فقط حساب عدد المكونات التي استجابت ثم المتابعة عند الوصول إلى رقم متوقع معين (2 في هذه الحالة) على سبيل المثال:

 this.$root.$emit('thruster-mounted') // in B and C
// instead of 
 this.$root.$emit('thruster-1-mounted') // for B and 2 for C

// then count the responses and resolve once they are >= 2 in component A

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

بدلاً من ذلك ، أود أن emit الحدث مباشرة إلى أصل A و B و C ، وليس على النطاق العام ، وأسمح للوالد بتحديد ما إذا كان سيتم عرض B و C ، أي

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

  <template>
    <a-component @rendered="showBandC = true" />
    <b-component v-if="showBandC" />
    <c-component v-if="showBandC" />
  </template>

ما هو الشيء المتعلق بـ A والذي سنحتاج في هذه الحالة إلى تقديمه قبل تصيير B و C.

نريد أن يقوم كل مكون بعمل فريد قبل تركيبه. ولكن لن يتم عرض جميع المكونات إلا عندما ينتهي كل مكون آخر من القيام بهذا العمل. هذه هي القصة هنا.
حظًا سعيدًا مع إدارة الدولة و v-if لمجرد التحكم في هذا ناهيك عن البيانات الفعلية التي من المحتمل أن تنتجها في متجر vuex . سينتهي بك الأمر بالحصول على الكثير من التعليمات البرمجية المكررة المكتوبة أينما تم استخدام المكون. لنفترض أن لديك مكونًا آخر يستضيف A و C فقط وبتكوين مختلف؟ يجب أن تكتب إدارة حالة vuex هذه v-if لإنجاح ذلك. هل ترى هذه المشكلة؟ دعني أوضح:

  // component Z totally different from foo, so we can't make this a component for reuse
  <template>
    <a-component @rendered="showBandC = true" />
    <c-component v-if="showBandC" />
  </template>
 ...
computed: {
showBandB() { ...vuex ...,
showBandC() { ...vuex ...,
}
  // component Foo totally unique, probably has other things it does
  <template>
    <b-component v-if="showBandC" />
    <c-component v-if="showBandC" />
  </template>
 ...
computed: {
// ok you could mixin this, fair, but complex nevertheless
showBandB() { ...vuex ...,
showBandC() { ...vuex ...,
}

..... وهكذا

بدلاً من مجرد استخدام المكونات دون فعل أي شيء للوالدين مثل:

  // component Z
  <template>
    <a-component />
    <b-component />
  </template>
  // component Foo
  <template>
    <b-component  />
    <c-component />
  </template>

... وهكذا دواليك

إذا كانت هناك أشياء في طريقة created() ، فلا شيء يمنع ذلك من ملء المتجر عبر فئة javascript أو استخدام وحدة store . لكن حالة الاستخدام الصريح ستكون أكثر فائدة ، أي ما هي تجربة المستخدم لقصة المستخدم التي لا يمكن التقاطها؟

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

الفكرة هي أن تحترم Vue عدم التزامن داخليًا قبل الانتقال إلى وظيفة الخطاف التالية.

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

يحتوي المكون الخاص بي على كل من async beforeMount و async mounted ، لكن الكود الموجود في mounted يتم تنشيطه قبل اكتمال الكود في beforeMount . كيف يمكننا منع mounted من التشغيل قبل اكتمال beforeMount ؟

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

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

تضمين التغريدة

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

هذا هو المكان:

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

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

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

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

هل كانت هذه الصفحة مفيدة؟
0 / 5 - 0 التقييمات