مكونات صفحة ويب SVG لإنترنت الأشياء وصانعيها (الجزء 1)
نشرت: 2022-03-10لا يزال سوق إنترنت الأشياء في مراحله الأولى ، ولكنه يكتسب قوة. نحن على أعتاب تاريخ إنترنت الأشياء. تضاعفت الأسواق أربع مرات في غضون خمس سنوات ، من 2015 إلى 2020. بالنسبة لمطوري الويب ، يعتبر نمو إنترنت الأشياء هذا كبيرًا. هناك بالفعل طلب كبير على تقنيات ويب إنترنت الأشياء.
سيتم نشر العديد من الأجهزة جغرافيًا مكانيًا ، وسيرغب أصحابها في التحكم عن بعد والإدارة. يجب إنشاء حزم الويب الكاملة من أجل إنشاء قنوات للتشغيل عن بُعد. أيضًا ، سيكون التفاعل مع واحد أو أكثر من أجهزة إنترنت الأشياء في وقت واحد. يجب أن يكون التفاعل في الوقت الحقيقي للعالم المادي.
تتعمق هذه المناقشة في متطلبات الواجهة باستخدام Vue.js كمحفز وتوضح طريقة واحدة لصفحة الويب للاتصال بالجهاز من بين العديد من التوابع.
فيما يلي بعض الأهداف المخطط لها لهذه المناقشة:
- إنشاء تطبيق ويب من صفحة واحدة SPWA يستضيف مجموعات من واجهات إنترنت الأشياء بين الإنسان والآلة (قد نطلق عليها "مجموعات اللوحات") ؛
- عرض قوائم معرفات مجموعة اللوحات كنتيجة للاستعلام عن الخادم ؛
- عرض لوحات المجموعة المحددة كنتيجة لاستعلام ؛
- تأكد من تحميل شاشة اللوحة كسول وتصبح متحركة بسرعة ؛
- تأكد من مزامنة اللوحات مع أجهزة إنترنت الأشياء.
إنترنت الأشياء والنمو السريع لصفحات الويب
يعد عرض الرسومات للتصور والتحكم عن بعد في الأجهزة جنبًا إلى جنب مع مزامنة صفحات الويب مع العمليات المادية في الوقت الفعلي ضمن مجال حل مشكلات صفحات الويب المتأصل في مستقبل إنترنت الأشياء هذا.
بدأ الكثير منا بحثنا عن تقنيات عرض إنترنت الأشياء ، ولكن هناك بعض معايير الويب جنبًا إلى جنب مع بعض تقنيات العرض التي يمكننا البدء في استخدامها الآن. بينما نستكشف هذه المعايير والتقنيات معًا ، يمكننا الانضمام إلى موجة إنترنت الأشياء هذه.
لوحات المعلومات وتصور البيانات مطلوبة. علاوة على ذلك ، فإن الطلب على تجاوز صفحات الويب التي توفر نماذج أو قوائم عرض أو محتوى نصي مرتفع. يجب أن تكون لوحات المعلومات الخاصة بإنترنت الأشياء رسومية متحركة. يجب أن تكون الرسوم المتحركة متزامنة مع العمليات المادية في الوقت الفعلي من أجل توفير رؤية حقيقية لحالة الجهاز للمستخدمين. حالة الآلة ، مثل احتراق اللهب أم لا ، تتفوق على حالة التطبيق وتوفر معلومات مهمة للمشغلين ، وربما حتى معلومات السلامة.
تتطلب لوحات المعلومات أكثر من تصور البيانات. علينا أن نضع في اعتبارنا أن جزء الأشياء من إنترنت الأشياء هو الأجهزة التي لا تحتوي فقط على مستشعرات ولكن أيضًا واجهات تحكم. في تطبيقات الأجهزة ، يتم توسيع MCU بمفاتيح التبديل ومفاتيح العتبة وإعدادات المعلمات والمزيد. ومع ذلك ، قد تحل صفحات الويب محل مكونات التحكم في الأجهزة .
لا جديد. كانت واجهات الكمبيوتر للأجهزة موجودة منذ فترة طويلة ، ولكن النمو السريع لاستخدام صفحات الويب لهذه الواجهات يعد جزءًا من تجربتنا الحالية. يسير WebRTC و Speech API على مسار تطوير بدأ في عام 2012. وقد تم تطوير WebSockets في إطار زمني مماثل.
لقد ظل إنترنت الأشياء في أذهاننا لفترة طويلة. لقد كانت إنترنت الأشياء جزءًا من الحوار البشري منذ عام 1832. ولكن ، إنترنت الأشياء والشبكات اللاسلكية كما أصبحنا نعرف أنه تم تصورها بواسطة Tesla في حوالي عام 1926. تخبرنا Forbes 2018 State of Iot عن التركيز الحالي في السوق على إنترنت الأشياء. تهم مطوري الويب ، تستدعي المقالة لوحات المعلومات:
"يقوم المتبنون أو المدافعون الأوائل لإنترنت الأشياء بتحديد أولويات لوحات المعلومات ، وإعداد التقارير ، وحالات استخدام إنترنت الأشياء التي توفر تدفقات بيانات متكاملة للتحليلات ، والتصور المتقدم ، واستخراج البيانات."
سوق إنترنت الأشياء ضخم. تقدم مقالة حجم السوق هذه تنبؤًا بعدد الأجهزة التي ستظهر: 2018: 23.14 مليار ين 2025: 75.44 مليار. وتحاول وضع رقم مالي عليها: 2014: \ 2.99 تريليون دولار 2020: 8.90 تريليون دولار. سيكون الطلب على مهارات إنترنت الأشياء هو الأسرع نموًا: إنترنت الأشياء تحت الطلب.
نظرًا لأننا نطور واجهات واضحة للتحكم في الأجهزة ومراقبتها ، فإننا نواجه مشكلة جديدة في تطوير واجهاتنا. كل المليارات من الأجهزة ستكون مملوكة للعديد من الأشخاص (أو المنظمات). أيضًا ، يجوز لكل شخص امتلاك أي عدد من الأجهزة. ربما ستتم مشاركة بعض الأجهزة.
غالبًا ما يكون للواجهات الحديثة التي تم تصميمها لعناصر التحكم في الماكينة تخطيط محدد جيدًا خاص بآلة معينة أو تثبيت عدد قليل من الأجهزة. على سبيل المثال ، في المنزل الذكي ، سيكون للنظام المتطور شاشة LCD مزودة بلوحات للأجهزة الموضوعة بعناية. ولكن ، مع تطورنا مع إصدار الويب من إنترنت الأشياء ، سيكون هناك أي عدد من اللوحات لدفق ديناميكي وحتى متنقل من الأجهزة.
تصبح إدارة اللوحات للأجهزة مشابهة لإدارة الاتصالات الاجتماعية على مواقع الويب الاجتماعية.
"يجب أن تكون واجهات المستخدم الخاصة بنا ديناميكية في إدارة أي لوحة ذات رسوم متحركة عالية في الوقت الفعلي يجب عرضها في أي وقت لكل مستخدم معين."
لوحة القيادة عبارة عن تطبيق ويب من صفحة واحدة SPWA. ويمكننا تخيل قاعدة بيانات للوحات. لذلك ، إذا كان مستخدم واحد سيصل إلى عدد من اللوحات والتكوينات لأجهزته المتناثرة حول الكوكب ، فإن SPWA يحتاج إلى الوصول إلى مكونات اللوحة عند الطلب. سيتعين تحميل الألواح وبعض JavaScript الداعم لها بشكل كسول.
"يجب أن تعمل واجهاتنا مع أطر عمل صفحات الويب التي يمكن أن تسمح بدمج روابط المكونات غير المتزامنة دون إعادة تهيئة أطر العمل الخاصة بها."
دعنا نستخدم Vue.js و WebSockets و MQTT و SVG لاتخاذ خطواتنا نحو سوق إنترنت الأشياء.
يوصى بالقراءة : إنشاء مخطط معلومات تفاعلي باستخدام Vue.js
بنية عالية المستوى لتطبيق ويب إنترنت الأشياء
عند تصميم واجهة صفحة ويب إنترنت الأشياء ، يكون لدى المرء دائمًا العديد من الخيارات. قد يكون أحد الخيارات هو تخصيص صفحة واحدة لجهاز واحد. قد يتم عرض الصفحة على جانب الخادم. سيكون للخادم مهمة الاستعلام عن الجهاز للحصول على قيم أجهزة الاستشعار الخاصة به ثم وضع القيم في الأماكن المناسبة في سلسلة HTML.
كثير منا على دراية بالأدوات التي تسمح لكتابة قوالب HTML بعلامات خاصة تشير إلى مكان وضع القيم المتغيرة. رؤية {{temperature}}
في مثل هذا القالب يخبرنا ويخبرنا محرك العرض بأخذ درجة الحرارة التي تم الاستعلام عنها من الجهاز واستبدال الرمز {{temperature}}
بها. لذلك ، بعد انتظار الخادم للاستعلام عن الجهاز ، واستجابة الجهاز ، وعرض الصفحة ، وتسليم الصفحة ، سيتمكن المستخدم أخيرًا من رؤية درجة الحرارة التي أبلغ عنها الجهاز.
بالنسبة لهذه الصفحة لكل بنية جهاز ، قد يرغب المستخدم بعد ذلك في إرسال أمر إلى الجهاز. لا توجد مشكلة ، يمكنه ملء نموذج HTML وإرساله. قد يكون للخادم مسار للجهاز فقط ، أو ربما يكون بطريقة أكثر ذكاءً ، مسارًا لنوع الجهاز ومعرف الجهاز. يقوم الخادم بعد ذلك بترجمة بيانات النموذج إلى رسالة لإرسالها إلى الجهاز ، وكتابتها إلى بعض معالج الجهاز وانتظر الإقرار. بعد ذلك ، قد يستجيب الخادم أخيرًا لطلب النشر ويخبر المستخدم أن كل شيء على ما يرام مع الجهاز.
تعمل العديد من أنظمة إدارة المحتوى بهذه الطريقة لتحديث إدخالات المدونة وما شابه. لا شيء يبدو غريبا عنه. يبدو أن HTML عبر HTTP كان له دائمًا تصميم للحصول على الصفحات التي تم تقديمها ولإرسال بيانات النموذج ليتم معالجتها بواسطة خادم الويب. علاوة على ذلك ، هناك الآلاف من أنظمة إدارة المحتوى للاختيار من بينها. لذلك ، من أجل تطوير نظام إنترنت الأشياء الخاص بنا ، يبدو من المعقول الخوض في تلك الآلاف من أنظمة إدارة المحتوى لمعرفة أيها مناسب للوظيفة. أو ، قد نطبق مرشحًا واحدًا على CMS للبدء به.
علينا أن نأخذ في الاعتبار طبيعة الوقت الحقيقي لما نتعامل معه. لذلك ، في حين أن HTML في شكلها الأصلي جيد جدًا للعديد من مهام المؤسسة ، إلا أنها تحتاج إلى القليل من المساعدة لكي تصبح آلية التسليم لإدارة إنترنت الأشياء. لذلك ، نحتاج إلى CMS أو خادم ويب مخصص يساعد HTML على القيام بمهمة إنترنت الأشياء هذه. يمكننا أيضًا التفكير في الخادم لأننا نفترض أن CMS توفر وظائف الخادم. نحتاج فقط إلى أن نضع في اعتبارنا أن الخادم يجب أن يوفر رسومًا متحركة تعتمد على الأحداث ، لذلك لا يمكن أن تكون الصفحة مطبوعة بنسبة 100٪ ثابتة.
فيما يلي بعض المعلمات التي قد توجه اختيارات صفحة الويب المرتبطة بالجهاز ، والأشياء التي يجب القيام بها:
- تلقي بيانات المستشعر ورسائل حالة الجهاز الأخرى بشكل غير متزامن ؛
- تقديم بيانات المستشعر للصفحة في العميل (نتيجة طبيعية تقريبًا لـ 1) ؛
- نشر الأوامر إلى جهاز معين أو مجموعة من الأجهزة بشكل غير متزامن ؛
- اختياريًا أرسل الأوامر عبر الخادم أو تجاوزها.
- الحفاظ بشكل آمن على علاقة الملكية بين الجهاز والمستخدم ؛
- إدارة عملية الجهاز الحرجة إما عن طريق عدم التدخل أو التجاوز.
تتبادر القائمة إلى الذهن عند التفكير في صفحة واحدة فقط تعمل كواجهة لجهاز محدد . نريد أن نكون قادرين على التواصل مع الجهاز بحرية عندما يتعلق الأمر بالأوامر والبيانات.
بالنسبة للصفحة ، نحتاج فقط إلى طلبها من خادم الويب مرة واحدة. نتوقع أن يوفر خادم الويب (أو التطبيق المرتبط به) مسار اتصال آمن. ولا يجب أن يكون المسار عبر الخادم ، أو ربما يجب أن يتجنب الخادم تمامًا حيث قد يكون للخادم مهام ذات أولوية أعلى بخلاف الاهتمام باتصال صفحة واحدة للبيانات القادمة من أجهزة الاستشعار.
في الواقع ، يمكننا تخيل البيانات القادمة من جهاز استشعار مرة واحدة في الثانية ، ولا نتوقع أن يوفر خادم الويب نفسه ثانية ثابتة من خلال التحديث الثاني لآلاف من تدفقات أجهزة الاستشعار الفردية مضروبة بآلاف المشاهدين. بالطبع ، يمكن تقسيم خادم الويب أو إعداده في إطار موازنة التحميل ، ولكن هناك خدمات أخرى مخصصة لتسليم أجهزة الاستشعار وتنظيم الأوامر إلى الأجهزة.
سيحتاج خادم الويب إلى تسليم بعض الحزم بحيث يمكن للصفحة إنشاء قنوات اتصال آمنة مع الجهاز. يجب أن نكون حذرين بشأن إرسال الرسائل على القنوات التي لا توفر بعض الإدارة لأنواع الرسائل التي تمر عبرها. يجب أن يكون هناك بعض المعرفة حول ما إذا كان الجهاز في وضع يمكن مقاطعته أو قد يكون هناك طلب لإجراء المستخدم إذا كان الجهاز خارج نطاق السيطرة. لذلك ، يمكن لخادم الويب مساعدة العميل في الحصول على الموارد المناسبة التي يمكنها معرفة المزيد عن الجهاز. يمكن إجراء المراسلة بشيء مثل خادم MQTT. وقد تكون هناك بعض الخدمات لإعداد خادم MQTT التي يمكن بدؤها عندما يحصل المستخدم على حق الوصول إلى لوحته عبر خادم الويب.
نظرًا للعالم المادي بمتطلباته في الوقت الفعلي وبسبب اعتبارات الأمان الإضافية ، يصبح مخططنا مختلفًا قليلاً عن الرسم الأصلي.
لا نتوقف هنا. لم نطلب إعداد صفحة واحدة لكل جهاز ، حتى لو كانت سريعة الاستجابة وتعالج الاتصال بشكل جيد. علينا أن نفترض أن المستخدم سوف يقوم بتسجيل الدخول إلى حسابه والوصول إلى لوحة التحكم الخاصة به. من هناك ، سيطلب بعض قائمة مشاريع المحتوى (على الأرجح المشاريع التي يعمل عليها). سيشير كل عنصر في القائمة إلى عدد من الموارد. عندما يختار عنصرًا عن طريق النقر أو النقر ، فسيحصل على إمكانية الوصول إلى مجموعة من اللوحات ، كل منها سيكون لديها بعض المعلومات حول مورد معين أو جهاز إنترنت الأشياء.
قد يكون أي عدد من اللوحات التي يتم تسليمها استجابةً للاستعلام الذي تم إنشاؤه نتيجةً لإجراءات واجهة المستخدم هي تلك اللوحات التي تتفاعل مع الأجهزة الحية. لذلك ، بمجرد ظهور لوحة ، من المتوقع أن تعرض نشاطًا في الوقت الفعلي وأن تكون قادرة على إرسال أمر إلى جهاز.
كيفية رؤية اللوحات على الصفحة هو قرار تصميم. قد تكون نوافذ عائمة ، أو قد تكون مربعات على خلفية قابلة للتمرير. ومع ذلك ، فإن الألواح ستحدد الوقت أو درجة الحرارة أو الضغط أو سرعة الرياح أو أي شيء آخر يمكنك تخيله. نتوقع أن تكون اللوحات متحركة فيما يتعلق بمقاييس الرسوم المختلفة. يمكن تقديم درجة الحرارة كمقياس حرارة ، والسرعة كمقياس سرعة نصف دائري ، والصوت كشكل موجة متدفقة ، وما إلى ذلك.
يقوم خادم الويب بمهمة توصيل اللوحات المناسبة إلى المستخدم المناسب مع الاستفسارات المقدمة إلى قاعدة بيانات اللوحات ونظراً إلى أن الأجهزة يجب أن تكون متاحة ماديًا. علاوة على ذلك ، نظرًا لوجود العديد من أنواع الأجهزة المختلفة ، فمن المحتمل أن تكون اللوحات لكل جهاز مختلفة. لذلك ، يجب أن يكون خادم الويب قادرًا على تقديم المعلومات التصويرية اللازمة لعرض اللوحة. ومع ذلك ، يجب ألا يتم تحميل صفحة HTML الخاصة بلوحة المعلومات بجميع اللوحات الممكنة. لا توجد فكرة عن العدد الذي سيكون هناك.
فيما يلي بعض المعلمات التي قد توجه اختيارات صفحة لوحة المعلومات ، والأشياء التي يجب أن تقوم بها:
- تقديم طريقة لاختيار مجموعات لوحات الجهاز ذات الصلة ؛
- الاستفادة من آليات اتصال الجهاز المتزامن لعدد من الأجهزة ؛
- تنشيط لوحات الجهاز عندما يطلبها المستخدم ؛
- دمج رسومات محملة بشكل كسول للحصول على تصميمات فريدة للوحات ؛
- الاستفادة من الرموز والمعلمات الأمنية فيما يتعلق بكل لوحة ؛
- الحفاظ على التزامن مع جميع الأجهزة الخاضعة لفحص المستخدم.
يمكننا أن نبدأ في رؤية كيف تتغير اللعبة ، ولكن في عالم تصميم لوحة القيادة ، تغيرت اللعبة قليلاً هنا وهناك لبعض الوقت. علينا فقط أن نحصر أنفسنا في بعض أدوات تطوير الصفحات المحدثة والمفيدة لننهض بنا.
لنبدأ بكيفية تقديم اللوحات. هذا يبدو بالفعل وكأنه وظيفة كبيرة. نحن نتخيل أنواعًا مختلفة من الألواح. ولكن ، إذا سبق لك استخدام DAW للموسيقى ، فسترى كيف استخدموا الرسومات لجعل اللوحات تبدو مثل الأجهزة التناظرية التي تستخدمها الفرق الموسيقية منذ فترة طويلة. يتم رسم جميع اللوحات في منصات العمل الصوتية الرقمية بواسطة المكونات الإضافية التي تعمل على الصوت. في الواقع ، قد تستخدم الكثير من إضافات منصات العمل الصوتية SVG لعرض واجهاتها. لذلك ، نقتصر على التعامل مع واجهات SVG ، والتي بدورها يمكن أن تكون أي رسم يمكننا تخيله.
اختيار SVG للوحات
بالطبع ، أنا أحب منصات العمل الصوتية الرقمية وسأستخدمها كمثال ، لكن SVG هو معيار لصفحة الويب. SVG هو معيار W3C. إنه لنقل الرسومات الخطية إلى صفحات الويب. اعتاد SVG أن يكون مواطنًا من الدرجة الثانية على صفحة الويب ، مطلوبًا للعيش في iFrames. ولكن ، منذ HTML5 ، أصبحت مواطنًا من الدرجة الأولى. ربما ، عندما يخرج SVG2 ، سيكون قادرًا على استخدام عناصر النموذج. في الوقت الحالي ، تعتبر عناصر النموذج كائنات غريبة في SVG. لكن هذا لا ينبغي أن يمنعنا من جعل SVG الركيزة للوحات.
يمكن رسم SVG وتخزينه للعرض ويمكن تحميله ببطء. في الواقع ، بينما نستكشف نظام المكونات ، سنرى أنه يمكن استخدام SVG لقوالب المكونات. في هذه المناقشة ، سنستخدم Vue.js لعمل مكونات للوحات.
رسم SVG ليس بالأمر الصعب ، لأن هناك العديد من برامج الرسم الخطي التي يسهل الحصول عليها. إذا أنفقت الأموال ، يمكنك الحصول على Adobe Illustrator ، الذي يقوم بتصدير SVG. لقد كان Inkscape بمثابة الانتقال إلى إنشاء SVG لبعض الوقت. إنه مفتوح المصدر ويعمل بشكل جيد على Linux ، ولكن يمكن تشغيله أيضًا على نظامي التشغيل Mac و Windows. بعد ذلك ، هناك العديد من برامج تحرير SVG لصفحات الويب المفتوحة المصدر ، وبعض إصدارات SaaS أيضًا.
لقد كنت أبحث عن محرر SVG مفتوح المصدر وقائم على الويب. بعد بعض النظر حولي ، عثرت على SVG-Edit. يمكنك تضمينه في صفحات الويب الخاصة بك ، ربما إذا كنت تقوم بإنشاء مدونة قائمة على SVG أو شيء من هذا القبيل.
عند حفظ عملك في ملف ، يقوم SVG-Edit بتنزيله في متصفحك ، ويمكنك التقاط الملف من دليل التنزيل الخاص بك.
تُظهر الصورة التي رسمتها بوابة AND تتحكم في وحدة تكامل. هذا ليس ما يتوقع المرء عادة رؤيته في لوحة لوحدة MCU. قد تحتوي اللوحة على زر لتغذية أحد مدخلات البوابة AND ، ربما. ثم قد يكون لديه شاشة عرض من ADC تقرأ إخراج المُدمج. ربما سيكون هذا مخططًا خطيًا على محور زمني. ستحتوي معظم اللوحات على رسومات تسمح للمستخدم بالتعامل مع ما يجري داخل وحدة MCU. وإذا كانت دائرتنا ستعيش في أي مكان ، فستكون داخل MCU.
مع ذلك ، يمكن استخدام مخططنا الإلكتروني لمناقشة الرسوم المتحركة. ما نريد القيام به هو إلقاء نظرة على SVG ومعرفة أين يمكننا الوصول إلى بعض علامات DOM التي نرغب في تغييرها بطريقة ما. يمكننا بعد ذلك تحريك SVG باستخدام القليل من JavaScript الفانيليا ومؤقت. لنجعل بوابة AND تومض بألوان مختلفة.
SVG الذي نبحث عنه موجود في مربع الكود التالي. لا يبدو الأمر ودودًا جدًا بالنسبة للمبرمج ، على الرغم من أن المستخدم سيكون سعيدًا جدًا. ومع ذلك ، لا تزال هناك بعض الإشارات التي يجب متابعتها للعثور على عنصر DOM الذي نرغب في العمل عليه. أولاً ، تمتلك معظم أدوات رسم SVG طريقة للحصول على خصائص الكائن ، على وجه الخصوص ، سمة id
. SVG-Edit له طريقة أيضًا. في المحرر ، حدد البوابة AND ولاحظ شريط الأدوات. سترى حقلاً id
class
CSS أيضًا.
إذا لم تتمكن من الوصول إلى أداة التحرير لسبب ما ، يمكنك فتح SVG في متصفح وفحص DOM. على أي حال ، وجدنا أن البوابة بها id
= "svg_1".
<svg width="640" height="480" xmlns="https://www.w3.org/2000/svg" xmlns:svg="https://www.w3.org/2000/svg"> <g class="layer"> <title>Layer 1</title> <path d="m80.59881,87.020171l14.714795,0m-14.714793,-11.938687l14.714797,0.000004m-0.033867,-6.543869l0,24.758504c42.377882,2.221929 43.364812,-27.139117 0,-24.758504zm47.366321,12.333056l-15.303943,0m-48.188699,-6.489897l1.454753,0l0,1.454751l-1.454753,0l0,-1.454751zm-0.068425,11.869359l1.454753,0l0,1.454753l-1.454753,0l0,-1.454753zm63.545246,-6.089294l1.454751,0l0,1.454751l-1.454751,0l0,-1.454751z" fill="#FF0000" stroke="#000000"/> <path d="m48.58886,119.662231l18.234678,0l2.523043,-7.173309l4.128604,13.808613l4.587337,-13.987948l4.013933,13.808613l4.35797,-13.629278l4.35797,13.718944l2.408353,-6.72497l18.349357,0m-64.482612,-0.623112l1.515724,0l0,1.515728l-1.515724,0l0,-1.515728zm64.484275,-0.103111l1.515721,0l0,1.515728l-1.515721,0l0,-1.515728z" fill="#FF0000" stroke="#000000" stroke-dasharray="null" stroke-linecap="null" stroke-linejoin="null" transform="rotate(90.3367 80.0675 119.304)"/> <polygon cx="108.5" cy="79.5" edge="0" fill="#ffffff" orient="x" shape="regularPoly" sides="3" strokeWidth="null" strokecolor="#000000"/> <polygon cx="215.5" cy="192.5" edge="0" fill="#ffffff" orient="x" shape="regularPoly" sides="3" strokeWidth="null" strokecolor="none"/> <polygon cx="165.5" cy="164.5" edge="0" fill="#ffffff" orient="x" shape="regularPoly" sides="3" strokeWidth="null" strokecolor="none"/> <polygon cx="161.5" cy="138.5" edge="0" fill="#ffffff" orient="x" shape="regularPoly" sides="3" strokeWidth="null" strokecolor="none"/> <polygon cx="160.5" cy="161.5" edge="0" fill="#ffffff" orient="x" shape="regularPoly" sides="3" strokeWidth="null" strokecolor="none"/> <g> <path d="m225.016923,53.008793l0,3.419331m-4.558966,-1.709666l9.11791,0m10.303228,4.235512l-25.770656,0m-34.429182,0l24.544724,0m0.220544,-4.058194l1.543807,0l0,8.164451l-1.543807,0l0,-8.164451zm7.939567,-4.473673l1.543805,0l0,16.999955l-1.543805,0l0,-16.999955zm-34.176663,8.126854l1.474036,0l0,0.747515l-1.474036,0l0,-0.747515zm61.677552,0.018809l1.474038,0l0,0.747515l-1.474038,0l0,-0.747515z" fill="#FF0000" sides="3" stroke="#000000" stroke-dasharray="null" stroke-linecap="null" stroke-linejoin="null" stroke-width="null"/> <polygon cx="171.5" cy="159.5" edge="43.256342" fill="#ffffff" orient="x" points="223.47406005859375,91.5 186.01296997070312,113.128173828125 186.01296997070312,69.871826171875 223.47406005859375,91.5 " shape="regularPoly" sides="3" stroke="#000000" stroke-width="null" strokeWidth="null" strokecolor="#000000"/> <line fill="none" stroke="#000000" stroke-dasharray="null" stroke-linecap="null" stroke-linejoin="null" stroke-width="null" x1="171" x2="186" y1="103.5" y2="103.5"/> <path d="m130.801817,80.659041l15.333707,0l2.12165,-4.564833l3.47178,8.787299l3.857534,-8.901421l3.375353,8.787299l3.664657,-8.673176l3.664657,8.730237l2.025206,-4.279526l15.430142,0m-54.224016,-0.396526l1.274586,0l0,0.964554l-1.274586,0l0,-0.964554zm54.225414,-0.065616l1.274584,0l0,0.964554l-1.274584,0l0,-0.964554z" fill="none" stroke="#000000" stroke-dasharray="null" stroke-linecap="null" stroke-linejoin="null" stroke-width="null"/> <line fill="none" stroke="#000000" stroke-dasharray="null" stroke-linecap="null" stroke-linejoin="null" stroke-width="null" x1="171.5" x2="171.5" y1="103.75" y2="135.388167"/> <line fill="none" stroke="#000000" stroke-dasharray="null" stroke-linecap="null" stroke-linejoin="null" stroke-width="null" x1="177.75" x2="177.75" y1="58.75" y2="80.255951"/> <line fill="none" stroke="#000000" stroke-dasharray="null" stroke-linecap="null" stroke-linejoin="null" stroke-width="null" x1="223.75" x2="266.854524" y1="91.75" y2="91.75"/> <line fill="none" stroke="#000000" stroke-dasharray="null" stroke-linecap="null" stroke-linejoin="null" stroke-width="null" x1="241.75" x2="241.75" y1="59.75" y2="91.754167"/> <line fill="none" stroke="#000000" stroke-dasharray="null" stroke-linecap="null" stroke-linejoin="null" stroke-width="null" x1="168.25" x2="180.75" y1="135.75" y2="135.75"/> <line fill="none" stroke="#000000" stroke-dasharray="null" stroke-linecap="null" stroke-linejoin="null" stroke-width="null" x1="169.75" x2="179.25" y1="138.5" y2="138.5"/> <line fill="none" stroke="#000000" stroke-dasharray="null" stroke-linecap="null" stroke-linejoin="null" x1="171" x2="179.75" y1="141.25" y2="141.25"/> </g> </g> </svg>
كل ما نحتاجه الآن هو القليل من JavaScript. نلاحظ أولاً أن سمة العنصر "ملء" موجودة. ثم هناك البرنامج البسيط التالي:
<html> <head> </head> <body> <!-- ALL THE SVG FROM ABOVE GOES HERE --> </body> <html> </svg> <script> // Set up a timer interval flash the color. var gateElement = document.getElementById("svg_1"); if ( gateElement ) { setInterval( () => { var fillC = gateElement.getAttribute("fill"); gateElement.setAttribute("fill", (fillC == "#00FF00") ? "#FF0000" : "#00FF00" ); }, 2000 ) } </script>
لاحظ أن ما لدينا هو الحد الأدنى من صفحات HTML. يمكنك قص الكود ولصقه في المحرر المفضل لديك. ثم لا تنس قص ولصق SVG لاستبدال التعليق. يتطلب إصداري من Chrome أن تكون الصفحة بتنسيق HTML من أجل الحصول على قسم JavaScript. لذلك ، هذا أحد المستعرضات لا يزال يتعامل مع SVG كشيء منفصل. لكن ما زال الطريق طويلاً منذ أيام <iframe>
.
إذا قمت بالقص واللصق بشكل صحيح ، فيمكنك إظهار الصفحة ورؤية بوابة AND تنتقل من الأحمر إلى الأخضر مرارًا وتكرارًا.
يوصى بقراءة : تحلل دائرة SVG إلى المسارات
لوحات البناء من مكونات VUE
نحن بالفعل في طريقنا لجعل أي لوحة واحدة تنبض بالحياة ، ولكن إذا أردنا إدارة مجموعات كبيرة من اللوحات بطرق معقولة ، فسنعمل على قطع عملنا من أجلنا. سيكون هذا هو الحال بشكل خاص إذا بنينا ببساطة على مثالنا الأول.
بينما يوضح لنا المثال الأول كيف يمكننا تغيير عرض الكائن بشكل غير متزامن ، فإنه لا يوضح لنا كيفية ربط العرض بحالة أي كائن بيانات ناهيك عن الكائن الذي يدير الجهاز. يمكننا بالتأكيد أن نفهم كيف يمكن استبدال العرض التوضيحي setInterval
fetch
، لكننا قد لا نحصل حتى على حالة الجهاز من خادم الويب الذي يخدم الصفحة التي تحتوي على SVG. أيضًا ، عندما نحصل على البيانات ، فإن برامجنا مطالبة الآن بمعرفة بنية DOM للصفحة المحددة.
لحسن الحظ ، أصبحت أطر العمل مثل Vue شائعة ، ويمكنها توفير الكثير من العمل لنا.
من السهل التعرف على Vue. وثائق Vue سهلة الوصول للغاية. لذلك ، إذا قفزت هذه المناقشة كثيرًا إلى الأمام ، فقد تقضي بعض الوقت في التعرف على Vue على موقع الويب الخاص بها. لكن ، هناك مناقشات جيدة جدًا داخل صفحات Smashing. كتب Krutie Patel مقالًا مذهلاً حول عمل رسم بياني. يخبرنا Souvik Sarkar كيف نبني لوحة معلومات الطقس باستخدام Vue.
مجموعة مختارة من اللوحات ذات الصلة
للخطوة الأولى ، يجب أن نعالج البحث عن مجموعات اللوحات. أحد أسباب القيام بذلك أولاً هو أنه على مستوى إطار تفاعلاتنا البشرية.
يبحث المستخدم عن شيء يثير اهتمامه. ربما يكون مهتمًا بجميع الأجهزة الموجودة في مواقع في بلدة واحدة. ربما لديه العديد من دفعات المنتجات السائلة ويريد التضييق على نوع واحد من المنتجات مع كل دفعة تحكمها مجموعة صغيرة من أجهزة إنترنت الأشياء. لذلك ، سيبحث المستخدم أولاً للحصول على قائمة صغيرة.
هذه هي العملية:
- ابحث عن مجموعات من اللوحات حسب الميزات / المعلمات.
- اعرض قائمة بالأيقونات التي تمثل المجموعات.
- حدد رمزًا (انقر / اضغط).
- ابدأ في استخدام اللوحات المحددة بالأيقونة عند ظهورها.
سبب آخر لكون هذه الخطوة الأولى جيدة هو أنه يمكننا استخدام Vue في أبسط صورة. لا حاجة لأدوات البناء. سنقوم فقط بتضمين vue.js
مع علامة البرنامج النصي في HTML. في الواقع ، ليس علينا حتى تنزيله. يوجد موقع يتم فيه تقديم نسخة عمل من vue.js
كل ما نحتاجه هو الوسم التالي:
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.js"></script>
لقد قمت بنسخ علامة البرنامج النصي مباشرة من وثائق Vue حول التثبيت.
الآن ، نحتاج إلى صفحة ويب يمكنها تحميل الرموز وتحويلها إلى شيء يمكن النقر عليه. Vue يجعل ذلك سهلاً للغاية. في الواقع ، لقد كتبت للتو تطبيقًا صغيرًا لإدارة قائمة Twitter باستخدام Vue. إنه يدير فقط حقول النص. نظرًا لأنه أبسط قليلاً من SPWA باستخدام الرموز ، يمكننا إلقاء نظرة عليه ثم تغييره ليكون إطار عمل تطبيق الصفحة الواحدة المطلوب.
فيما يلي جزء مما تبدو عليه الصفحة:
هذه تبدو كصفحة بسيطة إلى حد ما. كل إدخال رقمي خارجي هو فترة زمنية تحتوي على تغريدة واحدة أو اثنتين. التغريدة الثانية اختيارية. إذا قمت بتحرير تغريدة ، فإن آليات Vue تقوم بتحديث كائن JavaScript. تترك هذه الصفحة للمستخدم أن ينقر على زر "تحديث الإدخالات" ليخبر الخادم أن شيئًا ما قد تغير ، من خلال وظيفة معالج الزر الخاص به.
لكي يقوم معالج الأزرار بترحيل البيانات إلى الخادم ، يجب عليه تغيير كائن بيانات Vue إلى سلسلة JSON. الآن ، قد تتساءل عن مدى صعوبة ترجمة كائن Vue إلى JSON. اتضح أنه سطر واحد من التعليمات البرمجية. يمكنك العثور على السطر في التعليمات البرمجية المصدر التالية ، ولكن إذا كنت تريد العثور عليه بشكل أسرع ، فسيتم تمييزه في الفقرة التي تلي التعليمات البرمجية المصدر.
تبدو الصفحة بسيطة. المظاهر يمكن ان تكون خداعة. بالطبع ، تبدو الصفحة بسيطة ، لكن هل الكود بسيط؟ نعم ، إنه كذلك بالفعل! باستخدام Vue ، تدير الصفحة محتويات الحقول بطريقة سحرية تقريبًا. ها هو الكود:
<!DOCTYPE html> <html lang="en" prefix="og: https://ogp.me/ns#"> <!-- define microdata scope and type --> <head itemscope itemtype="https://schema.org/Article"> <title>Tweet Keeper</title> <style> body { margin: 2em; } .entryart { border: solid 1px navy; width: 80%; padding: 2px; padding-left: 6px; margin-bottom: 3px; background-color: #EEF4EE; } </style> <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.js"></script> </head> <body onload="GetTweets()"> <!-- some old fashioned handling --> <!-- The Vue app starts here. This is the HTML part of the Vue object --> <div> <!-- Recognize the name from the Vue doc --> <div itemscope itemtype="https://schema.org/Article"> <h1 itemprop="name">mangage tweets</h1> <p itemprop="description">My personal Tweet engine. This page accesses a personal tweet page that belongs to {{tweetOwner}}.</p> <!-- {{tweetOwner}} is in the data model. --> <button>Update Entries</button> </div> <!-- Here is a Vue loop for generating a lit --> <ol> <li v-for="tweet in tweets"> <!-- here is the first tweet represented as an object with a lable and tweet text --> <div class="entryart"> <input v-model="tweet.def[0].label" /> <input v-model="tweet.def[0].tweet" /> </div> <!-- here is the second tweet in the slot. But, notice that it is optional. --> <div class="entryart" v-if="tweet.def.length > 1"> <input v-model="tweet.def[1].label"/> <input v-model="tweet.def[1].tweet"/> </div> </li> </ol> </div> <script> var twtApp = new Vue({ el: '#tweetAppDiv', data: { tweets: [ // Where is the data? Still on the server.s ], tweetOwner : "Lucky Dude" // picked a name for demo } }); </script> </body> </html> <script> // Notice that you don't have to do everything in the Vue framework. // Here we are using some native API calls var gDefaultPostInfo = { // there server is beyond simple - an example from node.js docs method: 'POST', // or 'PUT' mode: "cors", // no-cors, cors, *same-origin cache: "no-cache", // *default, no-cache, reload, force-cache, only-if-cached credentials: "same-origin", // include, *same-origin, omit redirect: "follow", // manual, *follow, error referrer: "no-referrer", // no-referrer, *client body: "", headers:{ 'Content-Type': 'application/json' } } // // // recall the "onload" function GetTweets(event) { var url = "https://localhost:8080/twitlist1.json" // We have a fixed file name. fetch(url).then((response) => { // this is now browser native response.text().then((text) => { var newData = JSON.parse(text); // DATA UPDATE! This is it. twtApp.tweets = newData // the page update right away with new data. }); }); } function sendTweets() { // recall the button up above. This is not a Vue style button, but still in the Vue app. var url = "https://localhost:8080/" var data = twtApp.tweets; // GET THE DATA OUT OF VUE. That's all folks. // // so happens that Vue pulls out the right data and stringifies it. var jdata = JSON.stringify(data); // data can be `string` or {object}! // gDefaultPostInfo.body = jdata; // that's for fetch - not Vue related // fetch(url,gDefaultPostInfo).then(res => { // We use fetch to POST as well as GET res.json() }).then(response => { console.log('Success:', JSON.stringify(response)) // promises }).catch(error => { console.error('Error:', error) }); } // // // </script>
لذا ، فقط لإبراز الخطوط المذهلة التي تتحدث عن قوة إطار العمل ، دعنا نكرر هنا:
A. هذا هو سحب البيانات.
postOptionsObject.body = JSON.stringify(twtApp.tweets);
ب. هذا هو وضع البيانات في Vue ورؤية تحديث الشاشة:
twtApp.tweets = JSON.parse(text) // text is the server response
كم هذا العمل؟
يبدو أنه ستكون هناك طريقة لطيفة للتعبير عن كيفية تحديث البيانات للوحات لإنترنت الأشياء.
الآن ، دعنا نحول التغريدات إلى أيقونات قابلة للنقر مصممة لجلب المكونات من خادم الويب.
من التغريدات إلى أيقونات جلب اللوحة
يحب الناس استخدام SVG للرموز. لقد أحبوا هذا الاستخدام لـ SVG أكثر من استخدامه لأشياء أخرى بقدر ما أستطيع أن أقول. أنا أتابع فقط عدد مواقع الويب التي تبيع أو توزع الأيقونات المصنوعة في SVG. نقطة البيع هي أن الرسومات الخطية تحتوي على وحدات بايت أقل من الصور. وإذا كنت سأطلب قوائم من الصور ذات السلوك الشبيه بالأزرار ، فربما كنت قد التقطت ملفات PNG أو JPEG في الأيام التي كان فيها SVG في iframes. But, we can even find libraries in the Vue contributor lists that help us to a serving of icons.
We can turn the tweets page into an icon list returned as a search result. Just a little code has to be changed. Of course, there are a few things to be careful about if we want SVG icons to be loaded as buttons. Vue provides mechanisms for putting HTML into the application. These mechanisms have to be used or DOM elements fetched from the server don't get interpreted.
Here is the kind of rendering you can get from view if you follow your first impulse in creating a handlebars style variable location in the application DOM.
Here is the code that produces the result in the picture:
<div> <div class="entryart"> <span class="oneItem" v-for="icon in iconList"> {{icon}} </span> </div> </div> <script> var iconApp = new Vue({ el: '#iconAppTry', data: { iconList: [ // Where is the data? Still on the server. ], queryToken : "Thermo Batches" // picked a name for demo } }); </script>
Notice that we have gone from looping over tweets to looping over icons. tweet in tweets
changed into icon in iconList
. Our twtApp
hooks into the DOM element #tweetAppDiv
, while our iconApp
hooks into the DOM element #iconAppTry
. Within the Vue option object, the data
subobject has a tweets
in the first app, and iconList
in the second. The fields are both empty arrays that receive data when the fetch
routine does its job.
But, we have imitated our tweet app too closely. In the code above, the iconList is an array, and the server is expected to send an array of strings. So, let's say the server has sent us HTML, and we have it properly decoded with the array assigned to data.iconList
. Then, the picture above can be seen.
Now, let's change the code just a little. In this revised code, we can see the following:
v-html="icon">
Vue responds to the v-html syntax by putting in the DOM of the icon
element. Notice that the syntax is included after the loop directive as another attribute to the span
tag.
By removing the handlebars
syntax and using v-html
, our picture changes to something more comprehensible:
<div> <div class="entryart"> <span class="oneItem" v-for="icon in iconList" v-html="icon"> </span> </div> </div> <script> var iconApp = new Vue({ el: '#iconAppTry2', data: { iconList: [ // Where is the data? Still on the server. ], queryToken : "Thermo Batches" // picked a name for demo } }); </script>
While v-html
is a quick way to do things, the Vue team recommends using components to get the desired HTML into the page. That seems like a good idea, and we shall soon set about doing that.
But, let's use the v-html
syntax for our next example.
It's time to set up our working example for fetching SVG icons. Let's have those icons be responsive to a button click. Once those are working, we can get the panels associated with an icon.
Let's suppose that the SVG required for icons is stored in a database. For our example, we can just fetch a JSON file from the server. The grown-up version of the icon server would store many such files in a database, and deliver them to the page with the same mechanisms.
Also, it's best if the SVG arrives on the page URL encoded since we will be using JSON parse. The SVG can be decoded by calling JavaScript's decodeURIComponent
function.
In order to simulate the response to searching, we can make use of several JSON files. The page can have one button for each file. Here is the code for the page:
<!DOCTYPE html> <html lang="en" prefix="og: https://ogp.me/ns#"> <!-- define microdata scope and type --> <head itemscope itemtype="https://schema.org/Article"> <title>Search Bar</title> <style> body { margin: 2em; } div { margin: 6px; } .entryart { border: solid 1px navy; width: 80%; padding: 2px; padding-left: 6px; margin: 2px; margin-bottom: 3px; background-color: #EEF4EE; } .oneItem { background-color: #EEFFFF; margin: 2px; padding: 4px; border: solid 1px purple; } </style> <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.js"></script> </head> <body> <!-- some old fashioned handling --> <!-- The Vue app starts here. This is the HTML part of the Vue object --> <div> <!-- Recognize the name from the Vue doc --> <div> <h2 itemprop="name">Request MCU Groups</h2> <p itemprop="description">These are groups satistfying this query: {{queryToken}}.</p> <!-- {{tweetOwner}} is in the data model. --> <button>Find All</button> <button>Find 5 Point</button> <button>Find 6 Point</button> </div> <!-- Here is a Vue loop for generating a lit --> <div class="entryart"> <button v-for="iconEntry in iconList" @click="goGetPanel(iconEntry.name)" > <div v-html="iconEntry.icon"> </div> </button> </div> </div> <script> var iconApp = new Vue({ el: '#iconAppTry', data: { iconList: [ // Where is the data? Still on the server. ], queryToken : "Thermo Batches" // picked a name for demo }, methods : { goGetPanel: (pname) => { // `this` inside methods points to the Vue instance alert('Hello ' + pname + '!') } } }); </script> </body> </html> <script> // // recall the "onclick" on the <buttons> function GetIcons(points) { // special file names instead of search parameters // var url = (points == 11) ? "https://localhost:8080/batchQuery-all.json" : ((points == 5) ? "https://localhost:8080/batchQuery-five.json" : "https://localhost:8080/batchQuery-six.json") fetch(url).then((response) => { // this is now browser native response.text().then((text) => { var newData = JSON.parse(text); // DATA UPDATE! This is it. newData = newData.map(obj => { obj.icon = decodeURIComponent(obj.icon); return(obj) }); iconApp.iconList = newData; // the page update right away with new data. }); }); } </script>
Here is one display of icons that have been fetched from the server:
The data being sent is an array with the following kind of structure:
{ "style" : { "color" : "red", "backgroundColor" : "yellow" }, "icon" : svg1, "name" : "thermos" },
هنا ، svg1
هو SVG مأخوذ من ملف. بالطبع ، كان الخادم الصالح قد أخذ الهيكل من قاعدة البيانات ، حيث سيتم تخزين SVG في الهيكل.
هنا مقتطف من الكود أعلاه. هذا هو الكود الذي يجلب JSON ويضع مجموعة الهياكل في تطبيق Vue. يمكنك أن ترى هيكل الوعد fetch
قيد الاستخدام. يتم تحليل النص ، وفي السطر التالي ، يتم فك تشفير SVG المشفر. سطر واحد آخر ، و Vue يقوم بتحديث الصفحة. سيكون عدد الأزرار في شريط الأزرار مساويًا لطول مجموعة JSON.
fetch(url).then((response) => { // this is now browser native response.text().then((text) => { var newData = JSON.parse(text); // DATA UPDATE! This is it. newData = newData.map(obj => { obj.icon = decodeURIComponent(obj.icon); return(obj) }); // the page update right away with new data. iconApp.iconList = newData; }); });
الآن ، فقط اثنين من المقتطفات. تطبيق Vue. سيلاحظ القارئ أنه تم تضمين التوجيه @click
على الأزرار. يتم تمرير عنصر البيانات ، iconEntry.name
، إلى طريقة ضمن علامات الاقتباس.
يتم تحديد الطريقة في تطبيق Vue:
<div class="entryart"> <button v-for="iconEntry in iconList" @click="goGetPanel(iconEntry.name)" > <div v-html="iconEntry.icon"> </div> </button> </div> </div>
هنا هو المقتطف لتعريف الأساليب. يُضاف كائن methods
بعد كائن data
مباشرةً داخل كائن معلمة التطبيق:
, methods: { goGetPanel: (pname) => { // `this` inside methods points to the Vue instance alert('Hello ' + pname + '!') } }
يجب أن يجد القارئ تعريف goGetPanel
، وقد تمت الإشارة إلى استخدامه لمعالج @click
. في تطبيقنا النهائي ، يمكن استبدال استدعاء alert
بوظيفة تجلب اللوحات من الخادم.
مكتبة مكونة للوحات إنترنت الأشياء
يمكننا فقط أن نقرر أن اللوحات التي نجلبها من الخادم يمكن أن تكون HMTL أو مجرد رسومات SVG ، ولكن إذا كانت هناك أنواع عديدة من اللوحات ، فإننا نأمل أن يتم تبسيط مهمة إنشاء اللوحات من خلال وجود مكتبات من المكونات اختر من. يمكننا أن نتخيل أنه يمكن تحسين برامج تحرير SVG للسماح بإسقاط مكونات المكتبة على الصور كجزء من التحرير. بعد ذلك ، إذا كان بإمكان محرر SVG إخراج نسخة من الصورة بعلامات مكون ، فإن استخدام Vue سيسمح بإنشاء الصورة مع ضمان أن أتمتة JavaScript والرسوم المتحركة منسوجة بدقة معًا. لمناقشتنا ، يمكن لبعض التحرير اليدوي أن يساعدنا في الوصول إلى هناك.
إذا أردنا إنشاء لوحات من مكونات Vue ، فمن الأفضل لنا معرفة كيفية صنع المكونات ثم تجميعها معًا في شيء مفيد. سيتعين علينا التبديل إلى استخدام أدوات سطر الأوامر المقدمة من Vue وتنظيم سير العمل لدينا.
عناصر
تشير وثائق Vue إلى أن قسم data
المكون (كائن فرعي) لتعريف المكون يجب أن يكون دالة تقوم بإرجاع البيانات. والسبب في ذلك هو أن Vue يحتاج إلى إبقاء البيانات منفصلة بين الحالات. لذلك ، في الانتقال من تهيئة تطبيق Vue إلى تعريف المكون ، هناك تغيير صغير آخر في الكود.
في هذا المقتطف الأول من الكود ، تتم تهيئة تطبيق Vue:
var iconApp = new Vue({ el: '#iconApp', data: { // this is the data field that can be easily updated }, methods : { ... } });
في هذا المقتطف الجديد من التعليمات البرمجية ، يتم تعريف المكون وتسجيله. أولاً ، لاحظ أنه بدلاً من إنشاء مثيل new Vue
، يتم تسجيل مكون يسمى iconic
. بعد ذلك ، يُرجع حقل data
البيانات المخصصة لأي مثيل iconic
ينشئه تطبيق Vue. أخيرًا ، يوجد حقل template
في نهاية تسجيل المكون. يمكن أن يكون أي HTML قد تمت كتابته على صفحة الويب لعرض المكون جزءًا من template
.
Vue.component('iconic', data: () => { var instanceData = { // data fields named for the // variables appearing in the template onevar : "test" } return(instanceData); }, methods : { ... }, template: '<div>This appears in every instance {{onevar}}</div>' });
لذلك ، يمكننا تخيل لوحة مع موازين الحرارة. لذلك ، إذا قدم شخص ما مكون thermometer
، فإننا نتوقع تعريف مكون في مكان ما في الكود الخاص بنا. كما:
Vue.component('thermometer', data: () => { var instanceData = { // data fields named for the // variables appearing in the template temperature : 0 } return(instanceData); }, methods : { ... }, template: '<div>Some SVG will go here</div>' });
نحاول إنشاء شيء يشبه هذا:
مكون مقياس الحرارة مشابه جدًا للمكونات الأولى التي ستصادفها في دروس Vue التعليمية. ولكن ، من الصعب معرفة كيفية تحديثه. هناك طريقة أفضل لتحديد عنصر التفاعل باستخدام الخصائص. وذلك في الآتي:
Vue.component('thermometer', { props: ['temperature'], computed : { y: function() { var t = this.temperature/100; var h = 54.724472; var y_bar = 41.176476 // starts near the top // pretend the scale is 1 to 100, so that the temperature is a precentage return((1 - t)*h + y_bar) }, height : function() { var t = this.temperature/100; var h = 54.724472; // as high as the whole range var y_bar = 41.176476 // pretend the scale is 1 to 100, so that the temperature is a precentage return(t*h) } }, template: '#thermometer-template' })
لذلك ، بدلاً من تمثيل درجة الحرارة كعنصر بيانات. يتم تمثيله كممتلكات تحت props
. بعد ذلك ، هناك قسم جديد ، محسوب ، يوفر المتغيرات التي هي وظائف للخاصية. نرى هذا ، this.temperature
المستخدمة لكل من y
height
. يتم استخدام هذه المتغيرات المحسوبة في SVG كسمات لمستطيل.
في SVG ، ينمو y
من أعلى إلى أسفل. لذلك ، عندما نريد أن يكون المستطيل صغيرًا في الجزء السفلي من مقياس الحرارة ، يجب أن يكون y
للصندوق الأحمر أقل ، ويجب تقليل الارتفاع بحيث يظل ( y + height
) عند مقياس الحرارة صفر.
لاحظ حقل template
في تعريف المكونات. إنه في الواقع معرف عنصر المستند. العنصر المشار إليه هو قسم البرنامج النصي بالنوع الخاص: type="text/x-template"
. عنصر البرنامج النصي هو مكان وجود SVG لمقاييس الحرارة. ويستفيد SVG من متغيرات Vue وشروط التحكم بحيث يمكن تعريف التفاعل.
هنا بعض من SVG:
<script type="text/x-template"> <svg xmlns:svg="https://www.w3.org/2000/svg" xmlns="https://www.w3.org/2000/svg" width="20" height="70" version="1.1" > <g transform="translate(0,-180)"> <g transform="matrix(2.0111869,0,0,1.0489665,-215.11053,144.5592)"> <rect stroke-linecap="null" stroke-linejoin="null" width="2.9665921" height="54.724472" x="111.90748" y="41.176476" /> <rect stroke-linecap="null" stroke-linejoin="null" width="2.9665921" x="111.90748" :height="height" :y="y" /> <g transform="matrix(0.76503813,0,0,1,26.586929,0)"> <line y2="57.306953" y1="57.306953" x2="113.15423" x1="107.22105" stroke-linejoin="null" stroke-linecap="null" /> <line y2="74.408356" y1="74.408356" x2="113.15423" x1="107.22105" stroke-linejoin="null" stroke-linecap="null"
يمكن للقارئ العثور على id="thermometer-template"
في الأعلى ، والنظر إلى أسفل إلى العناصر rect
، يمكن العثور على المتغيرات المحسوبة.
هنا يتم فصل الاستخدامات المتغيرة. صيغة الاختصار Vue لـ v-bind
قيد الاستخدام ، مع :height="height"
ونفس الشيء بالنسبة لـ y
:
x="111.90748" :height="height" :y="y"
عندما يعيّن أصل عناصر SVG المتغيرات التي تعمل كمدخلات لدرجة حرارة خاصية مقياس temperature
، يعيد Vue حساب height
و y
. نتيجة لذلك ، يتغير موضع الصندوق الأحمر وارتفاعه.
من المفيد الحصول على قائمة بتطبيق Vue الذي يستخدم مقياس الحرارة.
<body> <!-- The Vue app starts here. This is the HTML part of the Vue object --> <div> <!-- Recognize the name from the Vue doc --> <div> <h2 itemprop="name">Set Temperature</h2> <p itemprop="description">These are groups satistfying this query: {{queryToken}}.</p> <!-- {{tweetOwner}} is in the data model. --> <button @click="updateTemp(50,50)">mid</button> <button @click="updateTemp(20,80)">low</button> <button @click="updateTemp(80,20)">high</button> </div> <thermometer :temperature="temp1" ></thermometer> <thermometer :temperature="temp2" ></thermometer> </div> <script> var thermoApp = new Vue({ el: '#thermoApp', data: { temp1 : 30, temp2 : 60, queryToken : "HEAT" }, methods : { updateTemp: function (tval1,tval2) { this.temp1 = tval1; this.temp2 = tval2; } } }); </script> </body>
هذا هو كل شيء. هناك ثلاثة أزرار تستدعي طريقة updateTemp
لتطبيق thermoApp
Vue. يحتوي قسم البيانات على متغيرين لدرجة الحرارة. ويقوم كل thermometer
بتحديث درجة حرارته عندما تتغير القيم.
يمكن العثور على الكود الخاص بميزاني الحرارة الموضحين أدناه في HTML المخصص لتطبيق Vue.
<thermometer :temperature="temp1" ></thermometer> <thermometer :temperature="temp2" ></thermometer>
لاحظ أن التطبيق يستخدم الشكلية function
لتعريف الطريقة. تعريف updateTemp
بهذه الطريقة updateTemp: function (tval1,tval2)
بالوصول إلى متغير المثيل this
.
كذلك ، فإن تعريف updateTemp
بهذه الطريقة updateTemp: (tval1,tval2) =>
يعين this
إلى بنية بيانات داخلية لا تتفاعل وتقوم بتحديث العرض.
تجميع لوحة
يمكن أن تكون كل لوحة إنترنت الأشياء مكونًا. يوفر Vue طريقة لتعريف المكونات بالمكونات الفرعية. بدلاً من ذلك ، هناك آلية فتحة يمكن استخدامها لإنتاج مكون يمكنه الالتفاف حول أي محتوى HTML.
في الفقرات القليلة التالية ، لنلق نظرة على تكوين لوحة من المكونات الفرعية. هناك نوعان من النماذج التي تتبع بسرعة من الأمثلة لدينا. في حالة واحدة ، يمكن أن تكون موازين الحرارة مكونات فرعية يتم استدعاؤها في JavaScript. في حالة أخرى ، يتم تعريف المكونات بشكل مستقل ولكن تم ذكرها في HTML.
في كلتا الحالتين ، يمكن استخدام نفس HTML للقالب. هنا لوحتنا كقالب:
<script type="text/x-template"> <div> <thermometer :temperature="temp1" ></thermometer> <thermometer :temperature="temp2" ></thermometer> </div> </script>
الاختلاف الوحيد بين التفاصيل الأولى للتطبيق هو أن عنصر div
يحيط بميزاني الحرارة. سيرمي Vue خطأ إذا كان القالب يفتقد إلى مستوى أعلى من عنصر DOM. يجتاز div
متطلب Vue ، ويمكن تضمين العناصر المتعددة بداخله.
الآن ، قد نرى الترمومترين جنبًا إلى جنب. إن تمرير درجات الحرارة من الأعلى إلى الترمومتر النهائي له قيم تتدرج إلى أسفل. في المستوى الأعلى ، تنضم اللوحة إلى التطبيق عندما يتم تضمين سطر واحد في تطبيق DOM.
<themo-panel :temp1="temp1" :temp2="temp2" ></themo-panel>
يبدو أن نموذج اللوحة ، على الرغم من بساطته ، يشير إلى أنه يمكن تصميم اللوحات بسهولة من حيث المكونات. يبدو الأمر كما لو أن لغة لمكونات إنترنت الأشياء فقط ممكنة.
الآن ، تعريف القالب للوحة بسيط بما فيه الكفاية. هنا مع المكونات الفرعية المحددة بشكل مستقل:
Vue.component('thermo-panel', { props: ['temp1','temp2'], template: '#thermo-panel-template' });
هذا هو بقدر ما هو مطلوب لجعل اللوحة وظيفية. صحيح أن هذا الإصدار يعتمد على قائمة طويلة من الخصائص لتحديد القيم التي سيتم تحديثها عند وصول الرسائل إلى الصفحة. لكن هذه بداية جيدة. يؤدي تحديث كائن data
في المستوى الأعلى إلى تحريك موازين الحرارة. ومع ذلك ، نظرًا لتعقيد اللوحات ، قد تكون هناك حاجة إلى طريقة أخرى لإظهار التغيير.
بعد الإشارة إلى الطرق الأخرى لتحديد المكونات الفرعية ، بالنسبة للوحة ، يجب أن نلقي نظرة عليها. ها هو:
Vue.component('thermo-panel', { props: ['temp1','temp2'], template: '#thermo-panel-template', components: { // a sub component for the labels 'thermometer': { props: { temperature: Number, }, template: '#thermometer-template', computed : { y: function() { var t = this.temperature/100; var h = 54.724472; var y_bar = 41.176476 // starts near the top // pretend the scale is 1 to 100, so that the temperature is a precentage return((1 - t)*h + y_bar) }, height : function() { var t = this.temperature/100; var h = 54.724472; // as high as the whole range var y_bar = 41.176476 // pretend the scale is 1 to 100, so that the temperature is a precentage return(t*h) } } } } });
هناك بالتأكيد المزيد من التعليمات البرمجية ، ولكن هذا بسبب تضمين JavaScript لمكون thermometer
ضمن قائمة مكونات thermo-panel
. يقوم النهجان بنفس الوظيفة ، لكنهما يقدمان طرقًا مختلفة لتعريفات مكونات التغليف.
في الوقت الحالي ، أفضل طريقة هي الطريقة الأولى. يجب أن يكون من الأسهل بكثير مراجعة اللوحات واسترجاعها ديناميكيًا إذا كان تغيير القالب والخصائص مطلوبًا فقط. تحقيقا لهذه الغاية ، تشكل المكونات المحددة بشكل مستقل مكتبة مكونة. ولكن ، على الرغم من أن هذا يبدو أفضل ، إلا أنه من الملائم استخدام الطريقة الثانية ، التي تبدو أكثر تفصيلاً.
بالنظر إلى أنه يمكننا إنشاء لوحات سريعة الاستجابة من المكونات بطرق محددة بوضوح ، سأشرح كيف يمكننا إدارتها كقاعدة بيانات يمكنها إجراء استعلامات بسيطة في الجزء التالي من مقالتي.