بداية سريعة مع WebComponents

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

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

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

لذلك دعونا نبدأ.

أولاً ، قم بإنشاء دليل للمشروع وانتقل إليه.

mkdir mywebcomp cd mywebcomp 

الانتهاء:

 npm init 

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

قم بإنشاء ملف index.html بأبسط المحتويات في الدليل.

 <html lang="en"> <body> </body> </html> 

إضافة علامة لأحد العناصر ، يجب أن يحتوي الاسم على واصلة ، وهذه إشارة للنظام الفرعي CusomElements لمحاولة تعريف هذا العنصر على أنه بناء على العناصر القياسية.

 <html lang="en"> <body> <my-webcomp></my-webcomp> </body> </html> 

إضافة فئة معالج إلى علامة البرنامج النصي .

 <script type="module"> class MyWebComp extends HTMLElement { connectedCallback() { this.insertAdjacentHTML('beforeEnd', `<div>Hello</div>`) } } customElements.define('my-webcomp', MyWebComp); </script> 

في علامة البرامج النصية المعيارية ، حددنا فئة جديدة ، باستخدام طريقة customElements.define () ، حددناه وراء علامة my-webcomp . وبإضافة الكود إلى طريقة connectCallback () ، قدمنا ​​مكالمته عند إضافة تطبيق المكون إلى الشجرة. يمكن بالفعل عرض النتيجة في المتصفح:



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

 <html lang="en"> <body> <template id="myWebCompTemplate"> <div>Hello</div> </template> <my-webcomp></my-webcomp> <script type="module"> class MyWebComp extends HTMLElement { connectedCallback() { let tplEl = document.querySelector('#myWebCompTemplate'); let html = document.importNode(tplEl.content, true); this.appendChild(html); } } customElements.define('my-webcomp', MyWebComp); </script> </body> </html> 

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

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

  let tplEl = document.querySelector('#myWebCompTemplate'); let html = document.importNode(tplEl.content, true); 

اكتب في سطر واحد:

 let html = document.importNode(myWebCompTemplate.content, true); 

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

 <my-webcomp id="myWebComp"></my-webcomp> <script type="module"> class MyWebComp extends HTMLElement { connectedCallback() { let html = document.importNode(myWebCompTemplate.content, true); this.appendChild(html); } } customElements.define('my-webcomp', MyWebComp); </script> <script type="module"> myWebComp.showMessage(); </script> 

في هذا السيناريو ، سيتم عرض التنبيه على الفور عند تحميل الصفحة.

سنقوم الآن بتعليق معالج النقر بالماوس لمكوننا الذي سيعرض رسالة تنبيه.

 <my-webcomp id="myWebComp" onclick="this.showMessage(event)"></my-webcomp> <script type="module"> class MyWebComp extends HTMLElement { connectedCallback() { let html = document.importNode(myWebCompTemplate.content, true); this.appendChild(html); } showMessage(event) { alert("This is the message"); console.log(event); } } customElements.define('my-webcomp', MyWebComp); </script> 

الآن ، عند النقر فوق رسالة ، سيكون لدينا رد فعل على إجراءات المستخدم.



تقوم الوسيطة الخاصة بأسلوب showMessage () أيضًا بتعريف كائن حدث يقوم بتخزين بيانات الحدث ، مثل إحداثيات نقرة أو رابط للعنصر نفسه.

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

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

 <my-webcomp id="myWebComp" greet-name="John" onclick="this.showMessage(event)"></my-webcomp> <my-webcomp id="myWebComp2" greet-name="Josh" onclick="this.showMessage(event)"></my-webcomp> <script type="module"> class MyWebComp extends HTMLElement { connectedCallback() { let html = document.importNode(myWebCompTemplate.content, true); this.appendChild(html); } showMessage(event) { alert("This is the message " + this.getAttribute('greet-name')); console.log(event); } } customElements.define('my-webcomp', MyWebComp); </script> 

الآن ، عند النقر فوق الأولى ، سيتم عرض "هذه هي رسالة جون" ، والثانية ، "هذه هي رسالة جوش".

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

 <template id="myWebCompTemplate"> <div id="helloLabel">Hello</div> </template> <my-webcomp id="myWebComp" greet-name="John" onclick="this.showMessage(event)"></my-webcomp> <my-webcomp id="myWebComp2" greet-name="Josh" onclick="this.showMessage(event)"></my-webcomp> <script type="module"> class MyWebComp extends HTMLElement { connectedCallback() { let html = document.importNode(myWebCompTemplate.content, true); this.appendChild(html); this.querySelector('#helloLabel').textContent += ' ' + this.getAttribute('greet-name'); } showMessage(event) { alert("This is the message " + this.getAttribute('greet-name')); console.log(event); } } customElements.define('my-webcomp', MyWebComp); </script> 

اتضح مثل هذا:



بدلاً من .textContent ، يمكن أن يكون .innerHTML أو يمكنك استدعاء نفس الأسلوب .insertAdjacentHTML () على الكائن من المحدد الذي قمنا به في البداية.

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

  this.attachShadow({mode: 'open'}); 

الآن الحقيقة هي أن جميع مكالمات DOM لهذا يجب استبدالها بـ this.shadowRoot ، حيث لا يوجد الكثير منها.

 <script type="module"> class MyWebComp extends HTMLElement { connectedCallback() { let html = document.importNode(myWebCompTemplate.content, true); this.attachShadow({mode: 'open'}); this.shadowRoot.appendChild(html); this.shadowRoot.querySelector('#helloLabel').textContent += ' ' + this.getAttribute('greet-name'); } showMessage(event) { alert("This is the message " + this.getAttribute('greet-name')); console.log(event); } } customElements.define('my-webcomp', MyWebComp); </script> 

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

 myWebComp.shadowRoot.getElementById('helloLabel'); 

ثم إذا لم تغلق الشجرة بتمرير السمة المقابلة في طريقة .attachShadow () .

لقد حصلنا على الكثير من التعليمات البرمجية ووضعها مباشرة في ملف html ليس صحيحًا أيضًا. لذلك ، سنقوم بإنشاء ملف my-webcomp.js ونقل صفنا إليه مع بيان التصدير ، وإضافة استيراد هذه الفئة في علامة البرنامج النصي للحصول على هذا:

 <script type="module"> import { MyWebComp } from "./my-webcomp.js"; customElements.define('my-webcomp', MyWebComp); myWebComp.shadowRoot.getElementById('helloLabel'); </script> 

لن يؤثر هذا على الأداء ، ولكن الآن كل منطق أعمالنا منفصل في .js ، ويتم تنفيذ التهيئة في سمات html ، وأنظمة المستعرض المعيارية والمكونات تتولى تهيئة التهيئة غير المتزامنة.

ومع ذلك ، من الآن فصاعدًا ، سيفشل فتح index.html كـ local for development ، لأنه سيقوم المتصفح بحظر تنزيل البرنامج النصي من نظام الملفات. إذا كان لديك nodejs يمكنك وضع أبسط خادم ويب:

 npm i http-server -g 

وقم بتشغيله باستخدام أمر http-server في دليل المشروع ، عند بدء التشغيل ، سيخبر المضيف والمنفذ الذي يمكنك من خلاله فتح الصفحة

 http://127.0.0.1:8080 

والذي سيكون الآن عنوان صفحة التصحيح مع عنصرنا.

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

إضافة الحزم.

 npm i mocha chai wct-mocha --save-dev 

للقيام بذلك ، قم بإنشاء دليل الاختبار وإضافة ملف all.html التالي إليه:

 <!doctype html> <html> <head> <meta charset="utf-8"> <script src="../node_modules/mocha/mocha.js"></script> <script src="../node_modules/chai/chai.js"></script> <script src="../node_modules/wct-mocha/wct-mocha.js"></script> </head> <body> <script> WCT.loadSuites([ 'my-webcomp.tests.html', ]); </script> </body> </html> 

انسخ index.html الخاص بنا لاختبار / إعطاء الاسم my-webcomp.tests.html وإضافة محتوى الرأس نفسه كما هو الحال في all.html .

ومع ذلك ، سنحتاج الآن إلى استبدال التهيئة المعتادة والتلاعب بتلك التي يتم تنفيذها كجزء من التشغيل التجريبي:

 <script type="module"> import { MyWebComp } from "../my-webcomp.js"; customElements.define('my-webcomp', MyWebComp); suite('MyWebComp', () => { test('is MyWebComp', () => { const element = document.getElementById('myWebComp'); chai.assert.instanceOf(element, MyWebComp); }); }); </script> 

الآن عند الدخول

 http://127.0.0.1:8080/test/all.html 

سيتم عرض تقرير الاختبار.



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

 sudo npm install --global web-component-tester --unsafe-perm 

وتشغيل مثل هذا:

 wct --npm 

يمكن إضافة هذا السطر إلى قسم الاختبار في ملف package.json وتشغيله على النحو التالي:

 npm test 



يوصى باختبار كل طريقة لفئة مهمة كجزء من اختبار منفصل. إذا كان من الضروري إجراء تهيئة مشتركة لكل منها ، فينبغي تعريفها في طريقة suiteSetup () :

 suiteSetup(() => { }); 

داخل الجناح.

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

 npm publish 

أو على الأقل

 git push 

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

يمكنك التحقق من الكود الخاص بك مع المستودع: https://bitbucket.org/techminded/mywebcomp

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

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


All Articles