في العمل اليومي، عندما نحدد مكونًا ، يجب أن نأخذ في الاعتبار تغليفه ، أي هل تتوقع أن النمط المحدد في هذا المكون يعمل فقط على هذا المكون، أم أنك تريده أن يعمل عالميًا. في Angular، يمكن تغليف أنماط المكون داخل العنصر المضيف للمكون بحيث لا تؤثر على بقية التطبيق. يوفر مصمم المكونات خيارات تغليف يمكن استخدامها للتحكم في كيفية تطبيق تغليف العرض على أساس كل مكون. [توصيات البرامج التعليمية ذات الصلة: "البرنامج التعليمي الزاوي"]
هناك ثلاثة أوضاع للتغليف في Angular، وهي ViewEncapsulation.ShadowDom، وViewEncapsulation.Emulated، وViewEncapsulation.None.
تصدير التعداد ViewEncapsulation { /** * يحاكي سلوك تغليف Shadow DOM الأصلي عن طريق إضافة سمة محددة إلى ملف * العنصر المضيف للمكون وتطبيق نفس السمة على جميع محددات CSS المتوفرة * عبر {@link Component#stylesstyles} أو {@link Component#styleUrls styleUrls}. * * هذا هو الخيار الافتراضي. */ تمت محاكاته = 0، /** * لا يوفر أي نوع من تغليف أنماط CSS، مما يعني توفير جميع الأنماط * عبر {@link Component#stylesstyles} أو {@link Component#styleUrls styleUrls} قابلة للتطبيق * إلى أي عنصر HTML في التطبيق بغض النظر عن المكون المضيف. */ لا شيء = 2، /** * يستخدم واجهة برمجة تطبيقات Shadow DOM الأصلية للمتصفح لتغليف أنماط CSS، مما يعني أنه يقوم بإنشائها * ShadowRoot للعنصر المضيف للمكون والذي يتم استخدامه بعد ذلك للتغليف * جميع أنماط المكون. */ شادودوم=3 }
إذا لم يتم توفيرها، فسيتم الحصول على القيمة من CompilerOptions. خيار المحول البرمجي الافتراضي هو ViewEncapsulation.Emulated.
إذا تم تعيين السياسة على ViewEncapsulation.Emulated ولم يحدد المكون الأنماط أو styleUrls، فسيتم التبديل تلقائيًا إلى ViewEncapsulation.None.
هل اكتشفت لماذا لا يوجد 1 في نوع التعداد ؟ المزيد عن هذا لاحقا.
ضع جانبًا تغليف ShadowDom في Angular، دعنا أولاً نلقي نظرة على ما هو ShadowDOM.
يسمح Shadow DOM بربط شجرة DOM مخفية بشجرة DOM العادية - تبدأ بعقدة جذر الظل، أسفل هذه العقدة الجذرية، يمكن أن تكون أي عنصر، تمامًا مثل عنصر DOM العادي.
توجد هنا بعض المصطلحات الخاصة بـ Shadow DOM والتي نحتاج إلى فهمها:
يمكنك التعامل مع Shadow DOM بنفس طريقة التعامل مع DOM العادي - مثل إضافة العقد الفرعية، وتعيين الخصائص، وإضافة النمط الخاص بك إلى العقدة (على سبيل المثال، من خلال خاصية element.style)، أو إضافة أنماط إلى العقدة بأكملها. Shadow DOM (مثل إضافة الأنماط داخل العناصر). الفرق هو أن العناصر الموجودة داخل Shadow DOM لن تؤثر أبدًا على العناصر الموجودة خارجه (باستثناء :focus-within)، مما يسهل التغليف.
دعونا نلقي نظرة على مثال بسيط.
<!DOCTYPE html> <أتش تي أم أل> <الرأس> <ميتا محارف = "UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, original-scale=1.0"> <title>Shadow DOM</title> <نمط> فترة{ اللون: أخضر؛ } </نمط> </الرأس> <الجسم> <span>أنا الجذر</span> <div id="app"></div> <النص البرمجي> Let app = document.querySelector('#app'); Let Shadow1 = app.attachShadow({ mode: 'open'}); دع style1 = document.createElement('style'); style1.appendChild(document.createTextNode("span{color: red;}")); Shadow1.appendChild(style1); Letspan1 = document.createElement('span'); span1.textContent = 'أنا ممتد.'; Shadow1.appendChild(span1); </script> </الجسم> </html>
يحدد المثال أعلاه نمط الامتداد العام ونمط الامتداد في ShadowDOM ويمكن ملاحظة أنهما لا يتأثران ببعضهما البعض.
بعد فهم ماهية ShadowDOM، دعونا نلقي نظرة على تغليف ShadowDOM في Angular.
يستخدم Angular واجهة برمجة تطبيقات Shadow DOM المدمجة في المتصفح لتغليف عرض المكون في ShadowRoot (الذي يعمل كعنصر مضيف للمكون) وتطبيق الأنماط المتوفرة بطريقة معزولة. يعمل ViewEncapsulation.ShadowDom فقط في المتصفحات التي تحتوي على دعم مدمج لـ Shadow DOM. لا تدعمه جميع المتصفحات، ولهذا السبب يعتبر ViewEncapsulation.Emulated هو الوضع الافتراضي الموصى به.
على سبيل المثال، في المثال التالي، استخدم ViewEncapsulation.ShadowDom .
@عنصر({ المحدد: "المستخدم-الطفل"، templateUrl: 'UserChild.component.html'، الأنماط: [` ح3{ اللون: أحمر؛ } `]، التغليف: ViewEncapsulation.ShadowDom }) فئة التصدير UserChildComponent تنفذ OnInit { ... }
من الصفحة قيد التشغيل، يمكننا أن نرى أن مكون المستخدم الفرعي مغلف داخليًا في ShadowDOM، وأن النمط مغلف أيضًا بالداخل، مما لن يؤثر على النمط الخارجي.
يقومAngular بتعديل محددات CSS للمكون بحيث تنطبق فقط على عرض المكون ولا تؤثر على العناصر الأخرى في التطبيق (محاكاة سلوك Shadow DOM).
عند استخدام تغليف العرض الوهمي، تقوم Angular بالمعالجة المسبقة لجميع أنماط المكونات بحيث تنطبق فقط على عرض المكون. في DOM لتطبيق Angular قيد التشغيل، يحتوي العنصر الذي يحتوي على المكون الذي يستخدم نمط تغليف العرض الوهمي على بعض السمات الإضافية المرفقة:
<hero-details _nghost-pmm-5> <h3 _ngcontent-pmm-5>السيد فانتاستيك</h3> <الفريق البطل _ngcontent-pmm-5 _nghost-pmm-6> <h4 _ngcontent-pmm-6>الفريق</h4> </الفريق البطل> </hero-details>
هناك سمتان من هذا القبيل:
السمة | information_nghost |
---|---|
إلى | العنصر الذي يغلف عرض المكون ، والذي سيكون ShadowRoots في غلاف Shadow DOM الأصلي. هذا هو الحال عادة مع العنصر المضيف للمكون . |
_ngcontent | إلى العناصر الفرعية في طرق عرض المكونات ، ويتم استخدام هذه السمات لمطابقة العناصر مع ShadowRoots المحاكاة الخاصة بها (العناصر المضيفة ذات سمات _nghost المطابقة). |
القيم الدقيقة لهذه الخصائص هي تفاصيل التنفيذ الخاصة لـ Angular. يتم إنشاؤها تلقائيًا ويجب ألا تشير إليها في رمز التطبيق الخاص بك.
إنهم يستهدفون أنماط المكونات التي تم إنشاؤها، والتي يتم حقنها في أجزاء من DOM:
[_nghost-pmm-5] { عرض: كتلة؛ الحدود: 1 بكسل أسود خالص؛ } h4[_ngcontent-pmm-6] { لون الخلفية: أبيض؛ الحدود: 1 بكسل صلب #777؛ }
تتم معالجة هذه الأنماط لاحقًا بحيث يتم زيادة كل محدد CSS باستخدام السمة _nghost أو _ngcontent المناسبة. تضمن هذه المحددات المعدلة تطبيق الأنماط على طرق عرض المكون بطريقة معزولة ومستهدفة.
<p>الطفل يعمل!</
p> ص{ اللون: أخضر؛ }
@عنصر({ المحدد: "التطبيق الطفل"، templateUrl: './child.component.html'، styleUrls: ['./child.component.scss']، التغليف: ViewEncapsulation.Emulated }) فئة التصدير ChildComponent تنفذ OnInit { ... }
نتيجة إعداد ViewEncapsulation.Emulated هي عدم وجود Shadow DOM، ولكن يتم تغليف المكون من خلال آلية تغليف النمط التي توفرها Angular، بحيث لا يتأثر نمط المكون بالتأثيرات الخارجية. على الرغم من أن النمط لا يزال مطبقًا على المستند بأكمله، إلا أن Angular ينشئ محددًا [_ngcontent-oow-c11] لـ p. يمكن ملاحظة أن النمط الذي حددناه للمكون قد تم تعديله بواسطة Angular. بكل بساطة، على الرغم من أنه نمط عالمي، إلا أنه لن يؤثر على أنماط المكونات الأخرى بسبب المحدد التلقائي. إذا قمت بإضافة هذه السمة يدويًا إلى عناصر أخرى، فسيتم تطبيق النمط أيضًا على هذا العنصر.
لا يطبقAngular أي شكل من أشكال تغليف العرض، مما يعني أن أي أنماط محددة للمكون يتم تطبيقها فعليًا على مستوى العالم ويمكن أن تؤثر على أي عنصر HTML موجود في التطبيق. هذا النمط هو في الأساس نفس نمط تضمين الأنماط في HTML نفسه.
الأصل:
<p #caption>الوالد يعمل!{{count}}</p> <p #caption>الأول: {{count}}</p> <span class="red-font">الوالد</span> <app-child></app-child>
الطفل:
<div style="border: 1px Solid green;"> <p>الطفل يعمل!</p> <span class="red-font">الطفل</span> </div>
ص{ اللون: أخضر؛ } الخط الأحمر { اللون: أحمر؛ }
@عنصر({ المحدد: "التطبيق الطفل"، templateUrl: './child.component.html'، styleUrls: ['./child.component.scss']، التغليف: ViewEncapsulation.None }) فئة التصدير ChildComponent تنفذ OnInit { ... }
في Angular2.
@عنصر({ ...، التغليف: ViewEncapsulation.Native }) تصدير فئة UserComponent {
يؤدي إعداد ViewEncapsulation.Native إلى استخدام ميزة Shadow DOM الأصلية. ستعرض Angular المكون وفقًا لتنسيق Shadow DOM الذي يدعمه المتصفح. في الواقع، هذا هو ViewEncapsulation.ShadowDom الأحدث.
قدمنا ثلاث طرق لتغليف العرض الزاوي وخصائص كل منها. في العمل اليومي، يجب عليك اختيار طريقة التغليف وفقًا لسيناريوهات محددة.