صورة وسائل التواصل الاجتماعي التقطها أندريه تايسين على Unsplash
أسهل طريقة لزيادة أي عنصر DOM مدمج:
ليست هناك حاجة إلى عمليات تعبئة متعددة ، فكل المتصفحات الحديثة تعمل فقط™️
من الممكن توسيع HTML أو SVG أو أي مساحة اسم مخصصة أخرى، مثل MathML ، دون مشاكل
يمكن إنشاء العناصر من الصفر أو ترقيتها عند الطلب للحصول على ترطيب رائع
يتناسب مع 313 بايت (أساسي) أو 774 بايت مع تضمين عمليات رد الاتصال لدورة حياة العناصر المخصصة (لا يوجد شيء جديد لتعلمه)
يمكن اختبار هذا المثال مباشرة وهو يخدش سطح ما يمكن فعله بهذه الوحدة الصغيرة للغاية ولكنها قوية.
// const createRegistry = require('nonchalance');import createRegistry from 'nonchalance/core';// يقبل التصدير الافتراضي بشكل اختياري سياق `globalThis` like لكل تلك البيئات التي لا تحتوي على DOM أصلي./ / مثل هذا السجل يمكن أن يعرض أسماء الفئات المؤهلة بالإضافة إلى مرجع "المستند" // الذي سيتم استخدامه لإنشاء العناصر.const {HTML} = createRegistry();// توسيع أي عنصر لإنشاء عناصر مخصصة أو ترقيتها// من سجل لا يشارك شيئًا مع فئة السياق العامة، تمتد كلمة المرور HTML.Input { // سوف يرث حقل علامة ثابتة = "الإدخال" مُنشئ(...args) {super(...args);this.type = 'password'; } // تجنب البرامج النصية الضارة واستعادة أي كلمة مرور بسهولة الحصول على القيمة () {return '********'؛ } // حالة العرض التوضيحي: استمر في استخدام "القيمة" الأصلية عند تعيين كلمة المرور تعيين القيمة (سرية) {super.value = Secret؛ }}document.body.innerHTML = ` <form> <input type="text" name="user" placeholder="user"> <input type="password" name="password" placeholder="password"> <input type="submit"> </form>`;// ترقية العنصر المطلوب عبر كلمة مرور ClassTypenew جديدة(document.querySelector('[type="password"]'));// أو إنشاء مثيل جديد سر = كائن. تعيين (كلمة المرور الجديدة، { الاسم: "تمرير" ، القيمة: Math.random()، العنصر النائب: 'كلمة مرور وقت التشغيل'});const form = document.querySelector('form');form.insertBefore(secret,form.lastElementChild);
باستخدام وحدة الوظيفة المخصصة، من الممكن ترقية أي نوع من العناصر دون مواجهة خطأ المنشئ غير القانوني الذي يظهر في أي وقت تقوم فيه class extends HTMLSomethingElement {}
، عندما لا يتم تعريف هذه الفئة عالميًا كمدخل في تسجيل customElements
.
لا يقتصر الأمر على عدم وجود أي شيء مشترك عالميًا من خلال هذه الوحدة في السياق العالمي، بل إن كل عمل إضافي غريب للحصول على أي تمديد مدمج يعد غير ضروري على الإطلاق:
تحافظ العناصر الجديدة أو التي تم تمريرها دائمًا على السلسلة الجذرية النموذجية الخاصة بها
لا يمكن أن تحدث أي سمات إضافية أو أسماء متضاربة على الإطلاق
علاوة على ذلك، نظرًا لأنه يمكن إنشاء أي سجل HTML لكل وحدة أو مشروع لمشاركته بين مكوناته، فمن الممكن أيضًا تمرير إنشاء السجل هذا إلى أي بيئة globalThis
زائفة أو ساخرة، مع حقل document
على الأقل يكشف عن createElementNS(namespace, tagName)
، وفئة واحدة أو أكثر من المفترض أن يختبرها المشروع، مثل HTMLElement
و/أو أي فئة أخرى مطلوبة لنجاح هذا المشروع.
ومع ذلك، نظرًا لأن الهدف الأساسي لهذه الوحدة هو DOM ، يتم استخدام المرجع globalThis
كإعداد افتراضي معقول ولكن هذا لا يعني أنه تتم مشاركة أي شيء حول السجلات التي تم إنشاؤها من خلال التصدير الافتراضي.
لا . يمكن تلخيص طريقة عمل custom-function
على النحو التالي:
# a native <p> protoype chain HTMLParagraphElement -> HTMLElement -> Element -> Node # a <p> passed to new (class CustomP extends HTML.P {}) CustomP -> HTMLParagraphElement -> HTMLElement -> Element -> Node # a <p> passed to class AnotherP extends CustomP {} AnotherP -> CustomP -> HTMLParagraphElement -> HTMLElement -> Element -> Node
باختصار، إنشاء عنصر من خلال new AnotherP
أو ترقية عنصر عبر new AnotherP(liveParagraph)
يؤدي ببساطة إلى تحديث سلسلة النموذج الأولي، دون مطالبة العنصر بمغادرة DOM أو تغيير طبيعته الأصلية، حيث يتم الحفاظ على ذلك في سلسلة وراثة النموذج الأولي .
ملخص: تقوم السجلات غير المبالية ببساطة بترقية العناصر دون تغيير طبيعتها، تمامًا بنفس الطريقة التي يعمل بها المدمج الأصلي على توسيع العمل تحت الغطاء.
نعم ، إما عبر تصدير /jsx
أو من خلال /ref
.
حول /jsx يرجى الاطلاع على ما هو تصدير /jsx؟ قسم.
حول /ref يرجى الاطلاع على ما هو تصدير /ref؟ قسم.
يقوم تصدير /ce
تلقائيًا بترقية العناصر بطريقة متوافقة مع طرق connectedCallback
و disconnectedCallback
و attributeChangedCallback
الخاصة بالفئات، بالإضافة إلى حقل observedAttributes
الثابتة الخاصة بها.
تستخدم الوحدة نسخة مضبوطة من وحدة العناصر المخصصة التي تعمل بشكل جيد بالفعل.
شاهد هذا العرض التوضيحي المباشر على Codepen للحصول على فكرة عن كيفية عمل ذلك.
لا . من الناحية المجازية، تحتوي عناصر HTML على معنى دلالي وأداة مساعدة محددة جيدًا ومرغوبة بمجرد تشغيلها، بنفس الطريقة التي ستكون بها وظيفة JS ، إلى الأبد، وظيفة JS ، حتى لو كان Object.setPrototypeOf(() => {}, Number.prototype)
يحدث... هل يمكنك أن ترى أو توافق على مدى خطأ ذلك؟
لا تريد هذه الوحدة (وربما لا تستطيع أيضًا) الحماية من سوء استخدام ميزاتها، لذا تأكد من أنه كلما تمت ترقية عنصر ما، فإنه يحافظ على سلسلة النموذج الأصلي الخاص به خلف المشهد، أو أنك وحدك تقاتل ضد DOM . .. وهو أمر غير مريح تماما، إذا سألتني؟
باختصار، بنفس الطريقة customElements.define('my-link', class extends HTMLDivElement {}, {extends: 'a'})
لا معنى له، وتثق هذه الوحدة في أنه سيتم تجنب الفئات غير المنطقية لمستخدميها.
حاليًا، يشير التصدير الافتراضي/الرئيسي لهذه الوحدة إلى نفس التصدير /core
.
نظرًا لأن هذه الوحدة تفتح صندوق Pandora's Box ببساطته وحجم كود برنامجه البخاري، وفي الغالب لأنه لا يزال متأخرًا عن الإصدار 0.
، فأنا أحاول التفكير في ما يجب تضمينه في الفهرس، وإليك بعض أفكاري:
ألن يكون رائعًا أن يكون لديك وحدة قائمة على ESX تفهم المكونات المحددة بهذه الطريقة؟
ألن يكون رائعًا أن يكون لديك وظيفة JSX pragma التي تنشئ مكونات من خلال هذه الوحدة؟
ألن يكون من الرائع أن يكون لديك...(صاحب مكانك هنا)...؟
نعم، سيكون الأمر رائعًا، وإذا كان بإمكاني اتخاذ قرار بشأن كيفية تسمية التصدير الافتراضي، فأنا مستعد لجلب هذا الاسم من بين الأشياء الجيدة الأخرى كمدخل افتراضي لهذه الوحدة ... تابعنا أو من فضلك أعطني أفكار وتلميحات حول كيفية القيام بذلك
وحتى ذلك الحين، يرجى استخدام عمليات التصدير الصريحة للتأكد من أن التحديثات المستقبلية لن تعبث بمنطقك، وأعتذر إذا تسببت التغييرات الأخيرة في حدوث مشكلات لك، ولكنني متأكد تمامًا من أنه يمكنك بسهولة ربط ذلك أو فهمه وكان ذلك للأبد!
عندما تتم ترقية العناصر عن بعد، فمن الممكن أن تكون هذه العناصر ملحقة بها بعض الخصائص والتي لم تحصل على فرصة للمرور عبر ملحقاتها.
يضمن هذا المساعد ببساطة إزالة الخصائص الموروثة كمفاتيح عناصر خاصة بها ليتم تشغيلها بعد ذلك كأدوات وصول مباشرة.
استيراد createRegistry من 'nonchalance/ce'؛ مُنشئ(...args) {accessors(super(...args)); } الحصول على القيمة() {console.log('الحصول على القيمة', this._value);return this._value; } تعيين القيمة(_القيمة) {this._value = _value;console.log('قيمة المجموعة', this._value); }}// عنصر div الأصليconst div = document.createElement('div');div.value = 123;// ترقية جديد WithAccessors(div);// re-checkconsole.log(div.value);
شاهده مباشرة لاختبار المزيد.
يشبه تصدير /builtin
(248 بايت) تمامًا /core
إلا أنه لا يستخدم custom-function
خلف الكواليس، مما يعني أن:
ليس من الممكن استخدام new BuiltIn()
أو new BuiltIn(element)
لأن ذلك من شأنه أن يؤدي إلى حدوث خطأ، ما لم يتم تسجيله بالفعل كـ customElement المدمج الممتد
ويمكن استخدامه لأتمتة تسجيل المكونات، كما هو موضح في هذا العرض التوضيحي المباشر على CodePen
التحذير الرئيسي الوحيد حول هذا التصدير هو أنه نظرًا لأنه يعتمد على عناصر مخصصة قياسية حقيقية، فقد تكون هناك حاجة إلى polyfill المضمن لـ Safari أو WebKit، على سبيل المثال:
<!-- البرنامج النصي الموجود في أعلى الصفحة لمتصفح Safari فقط polyfill --><script>self.chrome ||self.netscape ||document.write('<script src="//unpkg.com/@webreflection/custom-elements -builtin"><x2fscript>');</script>
يرجى ملاحظة أنه على الرغم من السماح بمساحات أسماء HTML
و SVG
افتراضيًا مع الامتدادات المضمنة، إلا أن العناصر المخصصة لا تقبل امتدادات SVG بحيث لا يكون من الممكن عمليًا سوى امتدادات HTML مع التصدير الحالي /builtin
.
إن تصدير ./dummy
مخصص في الغالب لـ SSR ، مما يوفر نفس الأداة المساعدة لتوسيع الفئات التي ستحمل فقط حقل tag
ثابت.
من خلال الجمع بين /tag
من الممكن إجراء SSR بنسبة 100% مع عدم المبالاة والترطيب عن بعد.
استيراد createRegistry من 'https://unpkg.com/nonchalance/dummy'؛استيراد createTag من 'https://unpkg.com/nonchalance/tag'؛const {HTML} = createRegistry();class HelloDiv يمتد HTML.Div { ConnectCallback() {console.log('أنا هنا'); }}// إنشاء مساحة اسم قابلة لإعادة الاستخدام لـ hydraconst nmsp = {HelloDiv};// إنشاء علامة Transformerconst tag = createTag(nmsp);// تخيل استجابة الخادم بدلاً من ذلك // ملاحظة: هذا الرمز مخصص للعرض التوضيحي فقطconsole.log( tag`<!doctype html><script type="module">استيراد createRegistry من 'https://unpkg.com/nonchalance/ce';const {HTML} = createRegistry();const nmsp = {};for (const el of document.querySelectorAll('[data-comp]')) { const {comp} = el.dataset; حذف el.dataset.comp; nmsp[comp](el);</script><HelloDiv></HelloDiv>` .ينضم('') .تقليم() .replace('const nmsp = {};',`const nmsp = { ${[...Object.entries(nmsp)).map(([key, value]) => `${key}: ${ value}` ).join(',n')} };` ));
يقبل تصدير /jsx
(976 بايت) خيار createElement
إضافي ويعيد دالة jsx
التي يمكن استخدامها كـ @jsx pragma للتحويل، من بين كل شيء آخر يعمل بالفعل بشكل افتراضي في React أو Preact ، وكذلك الفئات الممتدة عبر سجل HTML أو SVG ، بما في ذلك جميع الميزات التي يجلبها /ce
إلى تلك الفئات: عناصر مخصصة مثل دورة الحياة مع بعض التوابل في الأعلى:
ستتلقى الفئات في منشئها الدعائم التي تم تمريرها على طول العنصر، مما يتيح الإشارات أو الوظائف الأخرى أو التعامل مع أي شيء يمكن معالجته بالفعل بواسطة مكونات JSX الافتراضية.
عند استدعاء المُنشئ، سيتم ملء العنصر بالفعل بعناصره الفرعية، مما يؤدي إلى تجنب الخدع المحتملة المعروفة بالعناصر المخصصة القياسية عند تحديد/تسجيل الفئات قبل تحليل المستند.
على غرار امتداد /builtin
، ليس من الممكن استخدام new Component(props)
ولكن من الممكن دائمًا استخدام <Component {...props} />
.
شاهده عمليًا مع React Live على CodePen.
DOM هو DOM ، بغض النظر عن عدد الاتجاهات غير المباشرة الموجودة بينهما. قد يختلف DX الخاص بك، وفقًا لميزات إطار العمل، ولكن إذا كانت React هي ما تبحث عنه، فهناك طريقة صغيرة ولكنها أنيقة ومعتمدة على ref
للترويج لعقد JSX العادية مع اللامبالاة/الأساسية أو اللامبالاة/ce :
الاستيراد المشار إليه من 'nonchalance/ref';// يشير إلى أنه سيتم تمرير المكون كمرجع// ملاحظة: هذا مجرد وكيل خفيف يمنح تكامل الفئة // بغض النظر عن استخدامه في Wildconst Component = Referenced(class Extends HTML. شعبة { buildor(...args) {super(...args);this.addEventListener('click', console.log); }});ReactDOM.render( <div ref={Component}>انقر فوقي</div>, document.body);
يمكن أيضًا استخدام الأداة المساعدة ref
كمصمم ديكور دون التأثير على أي ميزة من فئات اللامبالاة العادية. بالإضافة إلى ذلك، تتم ترقية كل عنصر مرة واحدة فقط بحيث يكون من الآمن إضافة مستمعين أو منطق في المُنشئ.
شاهد هذا العرض التوضيحي مباشرةً على Codepen لتتعرف عليه.
يسمح تصدير /selector
(796 بايت) بالتعريف المباشر لأي محدد CSS بحيث تقوم الفئة ذات الصلة تلقائيًا بترقية أي عنصر يطابق هذا المحدد.
يرجى ملاحظة أن هذا المحدد يجب أن يكون فريدًا قدر الإمكان وإلا فقد تحدث مفاجآت. استخدم فئات أو سمات data-
محددة لوصف محددك بشكل أفضل.
استيراد createRegistry من 'nonchalance/core';import {define } from 'nonchalance/selector';const { HTML } = createRegistry();const Special = Define('[data-comp="special"]', يمتد الفصل إلى HTML. شعبة { buildor(...args) {super(...args);this.textContent = 'أنا مميز!'; }});// سيحتوي على "أنا مميز!" النص مرة واحدة Liveocument.body.innerHTML = `<div data-comp="special"></div>`;
يسمح تصدير ./tag
(188 بايت) بتحويل القوالب بطريقة سهلة الترطيب.
يمكن استخدامه كقيمة وسيطة خلف العلامات الحرفية الكاملة للقالب ويمكن أن يحدث الترطيب بمجرد وصول هذه العناصر إلى DOM .
استيراد createRegistry من 'nonchalance/ce'؛استيراد createTag من 'nonchalance/tag'؛const {HTML} = createRegistry();class HelloDiv يمتد HTML.Div { ConnectCallback() {console.log('أنا هنا'); }}// إنشاء مساحة اسم قابلة لإعادة الاستخدام لـ hydraconst nmsp = {HelloDiv};// إنشاء علامة Transformerconst tag = createTag(nmsp);// demodocument.body.innerHTML سريع وقذر = tag`<HelloDiv />`.join( '');// مثال الترطيب for (const el of document.querySelectorAll('[data-comp]')) { const {comp} = el.dataset; حذف el.dataset.com؛ // قم بترقية العنصر مرة واحدة جديد nmsp[comp](el);}
شاهده مباشرة على CodePen.
نعم . تتيح كل من عمليات التصدير /core
و /ce
إمكانية إنشاء سجلات HTML و SVG افتراضيًا:
استيراد createRegistry من 'nonchalance/core';const {HTML, SVG} = createRegistry();class Circle Extends SVG.Circle { مُنشئ (خيارات) {Object .assis(super(), options) .setAttribute('fill', 'gold'); } تعيين cx(قيمة) { this.setAttribute('cx', value) } تعيين cy(value) { this.setAttribute('cy', value) } set r(value) { this.setAttribute('r', value) }}document.querySelector('svg').append( دائرة جديدة({cx: 100, cy: 100, r: 50}));
شاهده مباشرة على Codepen.
من الممكن أيضًا تمرير أي مساحة اسم إلى createRegistry(options)
باستخدام {MathML: "http://www.w3.org/1998/Math/MathML"}
كمثال.
يُسمح بأي مساحة اسم لها معنى document.createElementNS
، ولا توجد قيود على نوع عناصر DOM التي يمكننا ترقيتها.
لقد كانت لدي إجابة طويلة جدًا على هذا من قبل ولكن الملخص هو أن هذه الوحدة تستخدم المعايير كما هو منصوص عليها بواسطة W3C أو WHATWG أو ECMAScript ، وتتطلب أقل من 1 كيلو بايت للعمل في كل مكان.
هذه ليست عبارة عن polyfill، إنها أداة تساعدك على كتابة المكونات في عالم JS ولا تقلق من أن تتعارض هذه العناصر أو تتطلب أدوات أو لا تكون قابلة للنقل عبر أي مشروع مستهدف تريده/تحتاجه/تفضله.
باختصار، إذا كنت موافقًا على إضافة أقل من 1 كيلو بايت لتقديم مكونات عالمية لكل من عالم الواجهة الأمامية والخلفية، فقد وصلت إلى الوحدة النمطية الصحيحة؟
لا يوجد شيء أكثر تحرراً من أن تكون طفلاً مهملاً يلعب في الوحل ضد كل المفكرين الذين يقولون: " لا تفعلوا ذلك! ".
تمثل هذه الوحدة هذا الشعور بطريقة أو بأخرى من خلال الحرية التي توفرها ميزات JS الحديثة، مما يعرض بديلاً أنيقًا ومحمولًا وخفيف الوزن للغاية للتعقيد المتزايد باستمرار الذي يقدمه بدلاً من ذلك بائعو المتصفحات والمواصفات الحديثة، وكلها ضرورية لإجبار المطورين على الحل البديل للقدرة على التوسع ببساطة المضمنة وتحافظ على البساطة وإمكانية الوصول الرائعة التي يشتهر بها الويب.