كيفية إنشاء ونشر تطبيق المواد الزاوي

نشرت: 2022-03-10
ملخص سريع ↬ جولة تفصيلية حول إنشاء تطبيق ويب Angular 8 وتطبيق مُنشئ QR Code يعتمد كليًا على Angular أثناء استضافته على Netlify.

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

بعد تطوير تطبيق الويب ، فإن الخطوة التالية هي نشره. وهنا يأتي دور "Netlify" في الصورة. من خلال واجهة سهلة الاستخدام للغاية ، والنشر التلقائي ، وتقسيم حركة المرور لاختبار A / B والعديد من الميزات الأخرى ، تعد Netlify بالتأكيد أداة رائعة.

ستكون المقالة بمثابة جولة حول إنشاء تطبيق ويب Angular 8 باستخدام مكتبة Angular Material Design الرسمية. سننشئ تطبيق ويب منشئ رمز الاستجابة السريعة يعتمد بالكامل على Angular أثناء استضافته على Netlify.

يمكن العثور على ملفات هذا البرنامج التعليمي على GitHub ويتم نشر إصدار تجريبي هنا.

ابدء

  1. قم بتثبيت Angular 8 ،
  2. قم بإنشاء حساب GitHub ،
  3. قم بتثبيت Git على جهاز الكمبيوتر الخاص بك ،
  4. قم بإنشاء حساب Netlify.

ملاحظة : سأستخدم VSCode و Microsoft Windows على أنهما IDE ونظام التشغيل المفضلان ، على الرغم من أن الخطوات ستكون مماثلة لأي IDE آخر على أي نظام تشغيل آخر.

بعد اكتمال المتطلبات السابقة ، لنبدأ!

المزيد بعد القفز! أكمل القراءة أدناه ↓

Mocks والتخطيط

قبل أن نبدأ في إنشاء المشروع ، سيكون من المفيد التخطيط مسبقًا: ما نوع واجهة المستخدم التي نريدها في تطبيقنا؟ هل سيكون هناك أي قطع قابلة لإعادة الاستخدام؟ كيف سيتفاعل التطبيق مع الخدمات الخارجية؟

أولاً ، تحقق من نماذج واجهة المستخدم.

الصفحة الرئيسية (معاينة كبيرة)
إنشاء صفحة QR (معاينة كبيرة)
صفحة المحفوظات (معاينة كبيرة)

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

لا توفر النماذج بالأحجام الطبيعية فكرة عن شكل التطبيق وأسلوبه فحسب ، بل تفصل أيضًا بين مسؤولية كل صفحة.

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

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

إنشاء مشروع زاوي جديد

قم بتشغيل VSCode ، ثم افتح نافذة طرفية في VSCode لإنشاء مشروع Angular جديد.

المحطة الطرفية في VSCode (معاينة كبيرة)

سيتم فتح المحطة بمسار افتراضي كما هو موضح في الموجه. يمكنك التغيير إلى دليل مفضل قبل المتابعة ؛ في حالة Windows ، سأستخدم الأمر cd .

التنقل إلى المسار المفضل (معاينة كبيرة)

من الآن فصاعدًا ، لدى angular-cli أمر لإنشاء مشاريع ng new <project-name> . ما عليك سوى استخدام أي اسم مشروع فاخر تريده واضغط على إدخال ، على سبيل المثال ng new qr .

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

بالنسبة لهذا البرنامج التعليمي ، أدخل نعم للتوجيه وحدد CSS للتصميم. سيؤدي هذا إلى إنشاء مشروع Angular جديد:

إنشاء مشروع Angular جديد (معاينة كبيرة)

لدينا الآن مشروع Angular يعمل بشكل كامل. من أجل التأكد من أن كل شيء يعمل بشكل صحيح ، يمكننا تشغيل المشروع عن طريق إدخال هذا الأمر في Terminal: ng serve . عذرًا ، لكن انتظر ، ينتج عن هذا خطأ. ما الذي يمكن انا يحدث؟

خطأ في العرض (معاينة كبيرة)

لا تقلق. عندما تنشئ مشروعًا جديدًا باستخدام angular-cli ، فإنه يولد الهيكل العظمي بالكامل داخل مجلد مسمى على اسم المشروع المحدد في الأمر ng new qr . هنا ، سيتعين علينا تغيير دليل العمل الحالي إلى الدليل الذي تم إنشاؤه للتو. في Windows ، استخدم الأمر cd qr لتغيير الدليل.

الآن ، حاول تشغيل المشروع مرة أخرى بمساعدة ng serve :

تشغيل المشروع (معاينة كبيرة)

افتح مستعرض ويب ، انتقل إلى URL https: // localhost: 4200 لرؤية المشروع قيد التشغيل. يقوم الأمر ng serve بتشغيل التطبيق على المنفذ 4200 افتراضيًا.

تلميح : لتشغيله على منفذ مختلف ، نستخدم الأمر ng serve --port <any-port> على سبيل المثال ، ng serve --port 3000 .

هذا يضمن أن مشروعنا الأساسي Angular يعمل. هيا لنذهب.

نحتاج إلى إضافة مجلد المشروع إلى VSCode. انتقل إلى قائمة "ملف" وحدد "فتح مجلد" وحدد مجلد المشروع. سيظهر مجلد المشروع الآن في عرض Explorer على اليسار.

إضافة مكتبة المواد الزاويّة

لتثبيت مكتبة المواد الزاويّة ، استخدم الأمر التالي في النافذة الطرفية: ng add @angular/material . سيؤدي هذا (مرة أخرى) إلى طرح بعض الأسئلة مثل المظهر الذي تريده ، وما إذا كنت تريد رسومًا متحركة افتراضية ، وما إذا كان دعم اللمس مطلوبًا ، من بين أمور أخرى. سنقوم فقط باختيار سمة Indigo/Pink الافتراضية ، Yes لإضافة مكتبة HammerJS والرسوم المتحركة للمتصفح.

إضافة مادة الزاوي (معاينة كبيرة)

يقوم الأمر أعلاه أيضًا بتكوين المشروع بأكمله لتمكين دعم مكونات المواد.

  1. يضيف تبعيات المشروع إلى package.json ،
  2. يضيف خط Roboto إلى ملف index.html ،
  3. يضيف خط رمز التصميم متعدد الأبعاد إلى index.html الخاص بك ،
  4. يضيف أيضًا بعض أنماط CSS العالمية إلى:
    • إزالة الهوامش من الجسم ،
    • تعيين height: 100% في HTML والجسم ،
    • قم بتعيين Roboto كخط التطبيق الافتراضي.

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

إضافة الصفحة الرئيسية

الهيكل العظمي لمشروعنا جاهز الآن. لنبدأ بإضافة الصفحة الرئيسية.

(معاينة كبيرة)

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

  1. الشريط العلوي عبارة عن عنصر nav HTML بسيط يحتوي على زر نمط المادة ، وزر mat-button ، مع صورة ونص كعنصر ثانوي له. لون الشريط هو نفس اللون الأساسي الذي تم تحديده أثناء إضافة مكتبة المواد الزاويّة ؛
  2. صورة مركزية
  3. آخر ، mat-button ، مع مجرد نص كطفل له. سيسمح هذا الزر للمستخدمين بالانتقال إلى صفحة السجل ؛
  4. شارة العد ، matBadge ، المرفقة بالزر أعلاه ، توضح عدد رموز QR المحفوظة من قبل المستخدم ؛
  5. زر إجراء عائم ، mat-fab ، في الزاوية اليمنى السفلية له لون تمييز من السمة المحددة.

استطراداً قليلاً ، دعنا نضيف المكونات والخدمات الأخرى المطلوبة أولاً.

مضيفا الرأس

كما هو مخطط سابقًا ، يجب إعادة استخدام شريط التنقل ، فلنقم بإنشائه كمكون زاوية منفصل. افتح Terminal في VSCode واكتب ng gc header (اختصارًا لـ ng ، قم بإنشاء رأس مكون) واضغط على Enter. سيؤدي هذا إلى إنشاء مجلد جديد باسم "header" والذي سيحتوي على أربعة ملفات:

  • header.component.css : تستخدم لتوفير التصميم لهذا المكون ؛
  • header.component.html : لإضافة عناصر HTML ؛
  • header.component.spec.ts : لكتابة حالات الاختبار ؛
  • header.component.ts : لإضافة المنطق المستند إلى أنواع.
مكون الرأس (معاينة كبيرة)

لجعل العنوان يبدو كما كان في الصور ، أضف HTML أدناه في header.component.html :

 <nav class="navbar" [class.mat-elevation-z8]=true> <div> <button *ngIf="showBackButton" aria-hidden=false mat-icon-button routerLink="/"> <mat-icon> <i class="material-icons md-32">arrow_back</i> </mat-icon> </button> <span>{{currentTitle}}</span> </div> <button *ngIf="!showBackButton" aria-hidden=false mat-button class="button"> <img src="../../assets/qr-icon-white.png"> <span>QR Generator</span> </button> <button *ngIf="showHistoryNav" aria-hidden=false mat-button class="button" routerLink="/history"> <span>History</span> </button> </nav>

نصيحة : لإضافة ارتفاع لأي مكون مادي [class.mat-elevation-z8]=true ، يمكن تغيير قيمة الارتفاع عن طريق تغيير قيمة z ، وهي في هذه الحالة z8 . على سبيل المثال ، لتغيير الارتفاع إلى 16 ، استخدم [class.mat-elevation-z16]=true .

في مقتطف HTML أعلاه ، يتم استخدام عنصرين من عناصر المواد الزاويّة: mat-icon mat و mat-button/mat-icon-button . استخدامهم بسيط للغاية ؛ أولاً ، نحتاج إلى إضافة هذين كوحدات نمطية في app.module.ts كما هو موضح أدناه:

استيراد الوحدة mat-icon mat-button (معاينة كبيرة)

سيسمح لنا ذلك باستخدام هذين العنصرين الماديين الزاويتين في أي مكان في أي مكون.

لإضافة أزرار المواد ، يتم استخدام مقتطف HTML التالي:

 <button mat-button> Material Button </button>

هناك أنواع مختلفة من عناصر زر المواد المتاحة في مكتبة المواد الزاويّة ، مثل mat-raised-button mat-flat-button ، mat-fab وغيرها ؛ فقط mat-button في مقتطف الشفرة أعلاه بأي نوع آخر.

أنواع أزرار المواد (معاينة كبيرة)

العنصر الآخر هو mat-icon الذي يستخدم لإظهار الرموز المتوفرة في مكتبة أيقونات المواد. عندما تمت إضافة مكتبة المواد Angular في البداية ، تمت إضافة مرجع إلى مكتبة أيقونات المواد أيضًا ، مما مكننا من استخدام الرموز من مجموعة كبيرة من الرموز.

الاستخدام بسيط مثل:

 <mat-icon> <i class="material-icons md-32">arrow_back</i> </mat-icon>

يمكن استخدام العلامة <i> المتداخلة لتغيير حجم الرمز (هنا md-32 ) والتي ستجعل حجم الرمز 32 بكسل في الطول والعرض. يمكن أن تكون هذه القيمة md-24 و md-48 وما إلى ذلك. قيمة العلامة <i> المتداخلة هي اسم الرمز. (يمكن العثور على الاسم هنا لأي رمز آخر.)

إمكانية الوصول

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

نقطة واحدة يجب ملاحظتها هي أن عناصر HTML التي لها دلالاتها الأصلية (مثل nav ) لا تحتاج إلى سمات ARIA ؛ يعرف قارئ الشاشة بالفعل أن nav هو عنصر تنقل ويقرأه على هذا النحو.

تنقسم مواصفات ARIA إلى ثلاث فئات: الأدوار ، والحالات ، والخصائص. لنفترض أنه تم استخدام div لإنشاء شريط تقدم في كود HTML. ليس لديها أي دلالات أصلية ؛ يمكن أن يصف دور ARIA هذه الأداة على أنها شريط تقدم ، ويمكن أن تشير خاصية ARIA إلى خصائصها مثل إمكانية سحبها. ستصف حالة ARIA حالتها الحالية مثل القيمة الحالية لشريط التقدم. انظر المقتطف أدناه:

 <div role="progressbar" aria-valuenow="75" aria-valuemin="0" aria-valuemax="100"> </div>

وبالمثل ، يتم استخدام سمة aria شائعة الاستخدام: aria-hidden=true/false . القيمة الحقيقية تجعل هذا العنصر غير مرئي لقراء الشاشة.

نظرًا لأن معظم عناصر واجهة المستخدم المستخدمة في هذا التطبيق لها معنى دلالي أصلي ، فإن سمات ARIA الوحيدة المستخدمة هي لتحديد حالات رؤية ARIA. للحصول على معلومات مفصلة ، يرجى الرجوع إلى هذا.

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

لتصميم شريط التنقل ، أضف css أدناه في header.component.css :

 .navbar { position: fixed; top: 0; left: 0; right: 0; z-index: 2; background: #3f51b5; display: flex; flex-wrap: wrap; align-items: center; padding: 12px 16px; } .button { color: white; margin: 0px 10px; }

نظرًا لأننا نريد الاحتفاظ بمكون الرأس قابلاً لإعادة الاستخدام عبر المكونات الأخرى ، وبالتالي لتحديد ما يجب عرضه ، فسنطلبها كمعلمات من المكونات الأخرى. يتطلب هذا استخدام @Input() decorator والذي سيرتبط بالمتغيرات التي استخدمناها في header.component.html .

أضف هذه الأسطر في ملف header.component.ts :

 // Add these three lines above the constructor entry. @Input() showBackButton: boolean; @Input() currentTitle: string; @Input() showHistoryNav: boolean; constructor() { }

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

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

مضيفا التوجيه

يوفر Angular طريقة لتعيين عنوان URL إلى مكون معين. عندما يحدث بعض التنقل ، يراقب إطار العمل Angular عنوان URL ويستند إلى المعلومات الموجودة في ملف app-routing.module.ts ؛ يقوم بتهيئة المكون المعين. بهذه الطريقة لا تحتاج المكونات المختلفة لتحمل مسؤولية تهيئة المكونات الأخرى. في حالتنا ، يحتوي التطبيق على ثلاث صفحات قابلة للتنقل من خلال النقر على أزرار مختلفة. نحقق ذلك من خلال الاستفادة من دعم التوجيه الذي يوفره إطار العمل Angular.

يجب أن يكون المكون الرئيسي هو نقطة البداية للتطبيق. دعنا نضيف هذه المعلومات إلى ملف app-routing.module.ts .

مكون التوجيه الرئيسي (معاينة كبيرة)

يتم تعيين خاصية path كسلسلة فارغة ؛ يتيح لنا ذلك تعيين عنوان URL للتطبيق إلى مكون الصفحة الرئيسية ، مثل google.com الذي يعرض صفحة Google الرئيسية.

تلميح : لا تبدأ قيمة المسار مطلقًا بـ " / " ، ولكنها تستخدم بدلاً من ذلك سلسلة فارغة على الرغم من أن المسار يمكن أن يكون مثل search/coffee .

بالرجوع إلى مكون الصفحة الرئيسية ، استبدل محتوى home.component.html بهذا:

 <app-header [showBackButton]="false" [currentTitle]=""></app-header> <app-profile></app-profile> <!-- FAB Fixed --> <button mat-fab class="fab-bottom-right" routerLink="/create"> <mat-icon> <i class="material-icons md-48">add</i> </mat-icon> </button>

يتكون المكون المنزلي من ثلاثة أجزاء:

  1. مكون الرأس القابل لإعادة الاستخدام <app-header> ،
  2. مكون الملف الشخصي <app-profile> ،
  3. زر الإجراء العائم في أسفل اليمين.

يوضح مقتطف HTML أعلاه كيفية استخدام مكون الرأس القابل لإعادة الاستخدام في المكونات الأخرى ؛ نحن فقط نستخدم محدد المكون ونمرر المعلمات المطلوبة.

تم إنشاء مكون الملف الشخصي لاستخدامه كهيئة للصفحة الرئيسية - سننشئه قريبًا.

زر الإجراء العائم مع الرمز + هو نوع من زر المادة الزاوي من نوع mat-fab في أسفل يمين الشاشة. يحتوي على توجيه السمة routerLink الذي يستخدم معلومات المسار المتوفرة في app-routing.module.ts للتنقل. في هذه الحالة ، يحتوي الزر على قيمة المسار كـ / إنشاء والتي سيتم تعيينها لإنشاء مكون.

لجعل زر الإنشاء يطفو في أسفل اليمين ، أضف كود CSS أدناه في home.component.css :

 .fab-bottom-right { position: fixed; left: auto; bottom: 5%; right: 10%; }

نظرًا لأنه من المفترض أن يدير مكون الملف الشخصي نص الصفحة الرئيسية ، home.component.ts كما هو.

إضافة مكون ملف التعريف

افتح Terminal ، واكتب ng gc profile واضغط على Enter لإنشاء مكون ملف التعريف. كما هو مخطط سابقًا ، سيتعامل هذا المكون مع النص الأساسي للصفحة الرئيسية. افتح profile.component.html واستبدل محتواه بهذا:

 <div class="center profile-child"> <img class="avatar" src="../../assets/avatar.png"> <div class="profile-actions"> <button mat-raised-button matBadge="{{historyCount}}" matBadgeOverlap="true" matBadgeSize="medium" matBadgeColor="accent" color="primary" routerLink="/history"> <span>History</span> </button> </div> </div>

يوضح مقتطف HTML أعلاه كيفية استخدام عنصر matBadge في مكتبة المواد. لتتمكن من استخدامه هنا ، نحتاج إلى اتباع التدريبات المعتادة لإضافة MatBadgeModule إلى ملف app.module.ts . الشارات هي واصف حالة مصورة صغير لعناصر واجهة المستخدم مثل الأزرار أو الرموز أو النصوص. في هذه الحالة ، يتم استخدامه مع زر لإظهار عدد QR المحفوظة من قبل المستخدم. تحتوي شارة مكتبة المواد الزاوية على العديد من الخصائص الأخرى مثل تعيين موضع الشارة باستخدام matBadgePosition و matBadgeSize لتحديد الحجم و matBadgeColor لتعيين لون الشارة.

يلزم إضافة أصل صورة آخر إلى مجلد الأصول: تنزيل. احفظه في مجلد /assets الخاص بالمشروع.

افتح ملف profile.component.css وأضف هذا:

 .center { top: 50%; left: 50%; position: absolute; transform: translate(-50%, -50%); } .profile-child { display: flex; flex-direction: column; align-items: center; } .profile-actions { padding-top: 20px; } .avatar { border-radius: 50%; width: 180px; height: 180px; }

سيحقق CSS أعلاه واجهة المستخدم كما هو مخطط لها.

للمضي قدمًا ، نحتاج إلى نوع من المنطق لتحديث قيمة عدد المحفوظات حيث ستنعكس في matBadge المستخدمة سابقًا. افتح profile.component.ts وأضف المقتطف التالي بشكل مناسب:

 export class ProfileComponent implements OnInit { historyCount = 0; constructor(private storageUtilService: StorageutilService) { } ngOnInit() { this.updateHistoryCount(); } updateHistoryCount() { this.historyCount = this.storageUtilService.getHistoryCount(); } }

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

التخزين المحلي

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

يتم تخزين كل قطعة من البيانات في زوج مفتاح / قيمة. سنستخدم النص الذي تم إنشاء QR له كمفتاح وصورة QR المشفرة كسلسلة base64 كقيمة. قم بإنشاء مجلد كيان ، داخل المجلد ، قم بإنشاء ملف qr-object.ts جديد وأضف مقتطف الكود كما هو موضح:

نموذج كيان QR (معاينة كبيرة)

محتوى الفصل:

 export class QR { text: string; imageBase64: string; constructor(text: string, imageBase64: string) { this.imageBase64 = imageBase64; this.text = text; } }

عندما يحفظ المستخدم QR الذي تم إنشاؤه ، سننشئ كائنًا من الفئة أعلاه ونحفظ هذا الكائن باستخدام خدمة أداة التخزين.

قم بإنشاء مجلد خدمة جديد ، وسننشئ العديد من الخدمات ، ومن الأفضل تجميعها معًا.

مجلد الخدمات (معاينة كبيرة)

قم بتغيير دليل العمل الحالي إلى خدمات ، cd services ، لإنشاء خدمة جديدة ، استخدم ng gs <any name> . هذا اختصار ng generate service <any name> ، اكتب ng gs storageutil واضغط على إدخال

سيؤدي ذلك إلى إنشاء ملفين:

  • Storageutil.service.ts
  • تخزينutil.service.spec.ts

هذا الأخير هو لكتابة اختبارات الوحدة. افتح storageutil.service.ts وأضف هذا:

 private historyCount: number; constructor() { } saveHistory(key : string, item :string) { localStorage.setItem(key, item) this.historyCount = this.historyCount + 1; } readHistory(key : string) : string { return localStorage.getItem(key) } readAllHistory() : Array<QR> { const qrList = new Array<QR>(); for (let i = 0; i < localStorage.length; i++) { const key = localStorage.key(i); const value = localStorage.getItem(key); if (key && value) { const qr = new QR(key, value); qrList.push(qr); } } this.historyCount = qrList.length; return qrList; } getHistoryCount(): number { if (this.historyCount) { return this.historyCount; } this.readAllHistory(); return this.historyCount; } deleteHistory(key : string) { localStorage.removeItem(key) this.historyCount = this.historyCount - 1; }

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

افتح الآن ملف profile.component.ts مرة أخرى واستورد فئة StorageutilService لإنهاء مكون ملف التعريف بشكل صحيح.

تشغيل المشروع ، يمكننا أن نرى الصفحة الرئيسية كما هو مخطط لها.

إضافة إنشاء صفحة QR

لدينا صفحتنا الرئيسية جاهزة ، على الرغم من أن زر إنشاء / إضافة لا يفعل أي شيء. لا تقلق ، المنطق الفعلي مكتوب بالفعل. استخدمنا توجيه routerLink لتغيير المسار الأساسي لعنوان URL إلى /create ولكن لم تتم إضافة تعيين إلى ملف app-routing.module.ts .

لنقم بإنشاء مكون يتعامل مع إنشاء أكواد QR جديدة ، واكتب ng gc create-qr واضغط على Enter لإنشاء مكون جديد.

افتح ملف app-routing.module.ts وأضف الإدخال أدناه إلى مصفوفة routes :

 { path: 'create', component: CreateQrComponent },

سيؤدي هذا إلى تعيين CreateQRComponent مع URL /create .

افتح create-qr.components.html واستبدل المحتويات بهذا:

 <app-header [showBackButton]="showBackButton" [currentTitle]="title" [showHistoryNav]="showHistoryNav"></app-header> <mat-card class="qrCard" [class.mat-elevation-z12]=true> <div class="qrContent"> <!--Close button section--> <div class="closeBtn"> <button mat-icon-button color="accent" routerLink="/" matTooltip="Close"> <mat-icon> <i class="material-icons md-48">close</i> </mat-icon> </button> </div> <!--QR code image section--> <div class="qrImgDiv"> <img *ngIf="!showProgressSpinner" src={{qrCodeImage}} width="200px" height="200px"> <mat-spinner *ngIf="showProgressSpinner"></mat-spinner> <div class="actionButtons" *ngIf="!showProgressSpinner"> <button mat-icon-button color="accent" matTooltip="Share this QR"> <mat-icon> <i class="material-icons md-48">share</i> </mat-icon> </button> <button mat-icon-button color="accent" (click)="saveQR()" matTooltip="Save this QR"> <mat-icon> <i class="material-icons md-48">save</i> </mat-icon> </button> </div> </div> <!--Textarea to write any text or link--> <div class="qrTextAreaDiv"> <mat-form-field> <textarea matInput [(ngModel)]="qrText" cdkTextareaAutosize cdkAutosizeMinRows="4" cdkAutosizeMaxRows="4" placeholder="Enter a website link or any text..."></textarea> </mat-form-field> </div> <!--Create Button--> <div class="createBtnDiv"> <button class="createBtn" mat-raised-button color="accent" matTooltip="Create new QR code" matTooltipPosition="above" (click)="createQrCode()">Create</button> </div> </div> </mat-card>

يستخدم المقتطف أعلاه العديد من عناصر مكتبة المواد الزاويّة. كما هو مخطط له ، يحتوي على مرجع مكون رأس واحد حيث يتم تمرير المعلمات المطلوبة. التالي هو النص الأساسي لصفحة الإنشاء ؛ تتكون من بطاقة مادة زاويّة واحدة أو بطاقة mat-card مركّزة ومرتفعة حتى 12 بكسل مثل [class.mat-elevation-z12]=true مستخدمة.

تعد بطاقة المواد مجرد نوع آخر من الحاويات يمكن استخدامه كأي علامة div أخرى. على الرغم من أن مكتبة المواد توفر بعض الخصائص لتخطيط معلومات محددة جيدًا في mat-card مثل وضع الصورة والعنوان والعنوان الفرعي والوصف والإجراء كما يمكن رؤيته أدناه.

مثال على البطاقة (معاينة كبيرة)

في مقتطف HTML أعلاه ، استخدمنا mat-card تمامًا مثل أي حاوية أخرى. عنصر آخر في مكتبة المواد المستخدمة هو matTooltip ؛ إنه مجرد تلميح أداة آخر مع سهولة الاستخدام ، يتم عرضه عندما يحوم المستخدم فوق عنصر أو يضغط عليه لفترة طويلة. ما عليك سوى استخدام المقتطف أدناه لإظهار تلميح الأداة:

 matTooltip="Any text you want to show"

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

 matTooltip="Any text you want to show" matTooltipPosition="above"

إلى جانب matTooltip ، يتم استخدام mat-spinner لإظهار تقدم التحميل. عندما ينقر المستخدم على الزر "إنشاء" ، يتم إجراء مكالمة شبكة. هذا عندما يتم عرض مفتاح التقدم. عندما تعود مكالمة الشبكة بنتيجة ، فإننا نخفي فقط القرص الدوار. يمكن استخدامه ببساطة مثل هذا:

 <mat-spinner *ngIf="showProgressSpinner"></mat-spinner>

showProgressSpinner هو متغير منطقي يستخدم لإظهار / إخفاء مفتاح التقدم. توفر المكتبة أيضًا بعض المعلمات الأخرى مثل [color]='accent' لتغيير اللون ، [mode]='indeterminate' لتغيير نوع قرص التقدم. لن يُظهر زر زيادة ونقصان غير محدد تقدم المهمة بينما يمكن أن يحتوي الشخص المحدد على قيم مختلفة لتعكس تقدم المهمة. هنا ، يتم استخدام مفتاح دوار غير محدد لأننا لا نعرف المدة التي ستستغرقها مكالمة الشبكة.

توفر مكتبة المواد مجموعة متنوعة من textarea تتوافق مع إرشادات المواد ولكن لا يمكن استخدامها إلا باعتبارها منحدرة من mat-form-field . يعد استخدام منطقة النص المادي بسيطًا مثل HTML الافتراضي ، كما هو موضح أدناه:

 <mat-form-field> <textarea matInput placeholder="Hint text"></textarea> </mat-form-field>

matInput هو توجيه يسمح لعلامة input الأصلية بالعمل مع mat-form-field . تسمح خاصية placeholder بإضافة أي نص تلميح للمستخدم.

تلميح : استخدم الخاصية cdkTextareaAutosize textarea لجعلها قابلة لتغيير الحجم تلقائيًا. استخدم cdkAutosizeMinRows و cdkAutosizeMaxRows لتعيين الصفوف والأعمدة وجميعها معًا لإجراء تغيير تلقائي لحجم textarea حتى يصل إلى الحد الأقصى لمجموعة الصفوف والأعمدة.

لاستخدام كل عناصر مكتبة المواد هذه ، نحتاج إلى إضافتها في ملف app.module.ts .

إنشاء واردات وحدة QR (معاينة كبيرة)

هناك صورة عنصر نائب يتم استخدامها في HTML. قم بتنزيله وحفظه في مجلد /assets .

يتطلب HTML أعلاه أيضًا تصميم CSS ، لذا افتح ملف create-qr.component.ts وأضف ما يلي:

 .qrCard { display: flex; flex-direction: column; align-items: center; position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); width: 20%; height: 65%; padding: 50px 20px; } .qrContent { display: flex; flex-direction: column; align-items: center; width: 100%; } .qrTextAreaDiv { width: 100%; display: flex; flex-direction: row; justify-content: center; padding: 0px 0px; position: absolute; bottom: 10%; } .createBtn { left: 50%; transform: translate(-50%, 0px); width: 80%; } .createBtnDiv { position: absolute; bottom: 5%; width: 100%; } .closeBtn { display: flex; flex-direction: row-reverse; align-items: flex-end; width: 100%; margin-bottom: 20px; } .closeBtnFont { font-size: 32px; color: rgba(0,0,0,0.75); } .qrImgDiv { top: 20%; position: absolute; display: flex; flex-direction: column; align-items: center; justify-content: center; width: 100%; } .actionButtons { display: flex; flex-direction: row; padding-top: 20px; }

دعنا نربط واجهة المستخدم بالمنطق. افتح ملف create-qr.component.ts وأضف الكود أدناه ، تاركًا تلك الأسطر الموجودة بالفعل:

 export class CreateQrComponent implements OnInit { qrCodeImage = '../../../assets/download.png'; showProgressSpinner = false; qrText: string; currentQR; showBackButton = true; title = 'Generate New QR Code'; showHistoryNav = true; constructor(private snackBar: MatSnackBar, private restutil: RestutilService, private storageService: StorageutilService) { } ngOnInit() { } createQrCode() { //Check if any value is given for the qr code text if (!!this.qrText) { //Make the http call to load qr code this.loadQRCodeImage(this.qrText); } else { //Show snackbar this.showSnackbar('Enter some text first') } } public loadQRCodeImage(text: string) { // Show progress spinner as the request is being made this.showProgressSpinner = true; // Trigger the API call this.restutil.getQRCode(text).subscribe(image =>{ // Received the result - as an image blob - require parsing this.createImageBlob(image); }, error => { console.log('Cannot fetch QR code from the url', error) // Hide the spinner - show a proper error message this.showProgressSpinner = false; }); } private createImageBlob(image: Blob) { // Create a file reader to read the image blob const reader = new FileReader(); // Add event listener for "load" - invoked once the blob reading is complete reader.addEventListener('load', () => { this.qrCodeImage = reader.result.toString(); //Hide the progress spinner this.showProgressSpinner = false; this.currentQR = reader.result.toString(); }, false); // Read image blob if it is not null or undefined if (image) { reader.readAsDataURL(image); } } saveQR() { if (!!this.qrText) { this.storageService.saveHistory(this.qrText, this.currentQR); this.showSnackbar('QR saved') } else { //Show snackbar this.showSnackbar('Enter some text first') } } showSnackbar(msg: string) { //Show snackbar this.snackBar.open(msg, '', { duration: 2000, }); } }

لتزويد المستخدمين بالمعلومات السياقية ، نستخدم أيضًا MatSnackBar من مكتبة تصميم المواد. يظهر هذا كنافذة منبثقة من أسفل الشاشة ويبقى لبضع ثوان قبل أن يختفي. هذا ليس عنصرًا ولكنه خدمة يمكن استدعاؤها من كود Typescript.

يوضح المقتطف أعلاه الذي يحمل اسم الطريقة showSnackbar كيفية فتح شريط الوجبات الخفيفة ، ولكن قبل استخدامه ، نحتاج إلى إضافة إدخال MatSnackBar في ملف app.module.ts تمامًا كما فعلنا مع عناصر مكتبة المواد الأخرى.

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

أولاً ، استخدم CSS أدناه لتغيير ألوان الخلفية والمقدمة:

 ::ng-deep snack-bar-container.snackbarColor { background-color: rgba(63, 81, 181, 1); } ::ng-deep .snackbarColor .mat-simple-snackbar { color: white; }

ثانيًا ، استخدم خاصية تسمى panelClass لتعيين النمط على فئة CSS أعلاه:

 this.snackBar.open(msg, '', { duration: 2000, panelClass: ['snackbarColor'] });

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

يكمل هذا الخطوات الخاصة بكيفية إنشاء صفحة QR ، ولكن لا تزال هناك قطعة واحدة مفقودة. التحقق من ملف create-qr.component.ts سيظهر خطأ بخصوص القطعة المفقودة. القطعة المفقودة في هذا اللغز هي RestutilService المسؤولة عن جلب صورة رمز الاستجابة السريعة من واجهة برمجة تطبيقات الطرف الثالث.

في الجهاز ، قم بتغيير الدليل الحالي إلى الخدمات عن طريق كتابة ng gs restutil والضغط على Enter. سيؤدي ذلك إلى إنشاء ملفات RestUtilService. افتح ملف restutil.service.ts وأضف هذا المقتطف:

 private edgeSize = '300'; private BASE_URL = 'https://api.qrserver.com/v1/create-qr-code/?data={data}!&size={edge}x{edge}'; constructor(private httpClient: HttpClient) { } public getQRCode(text: string): Observable { // Create the url with the provided data and other options let url = this.BASE_URL; url = url.replace("{data}", text).replace(/{edge}/g, this.edgeSize); // Make the http api call to the url return this.httpClient.get(url, { responseType: 'blob' }); } private edgeSize = '300'; private BASE_URL = 'https://api.qrserver.com/v1/create-qr-code/?data={data}!&size={edge}x{edge}'; constructor(private httpClient: HttpClient) { } public getQRCode(text: string): Observable { // Create the url with the provided data and other options let url = this.BASE_URL; url = url.replace("{data}", text).replace(/{edge}/g, this.edgeSize); // Make the http api call to the url return this.httpClient.get(url, { responseType: 'blob' }); }

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

يوفر Angular فئة HttpClient للتواصل مع أي خادم يدعم HTTP. يوفر العديد من الميزات مثل تصفية الطلب قبل إطلاقه ، واستعادة الاستجابة ، وتمكين معالجة الاستجابة عبر عمليات رد الاتصال وغيرها. لاستخدام نفس الشيء ، قم بإضافة إدخال لـ HttpClientModule في ملف app.module.ts .

أخيرًا ، قم باستيراد هذه الخدمة إلى ملف create-qr.component.ts لإكمال إنشاء رمز الاستجابة السريعة.

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

طلب التخزين المؤقت

يوفر Angular طريقة مبسطة لإجراء مكالمات HTTP ، HttpClient ، جنبًا إلى جنب مع HttpInterceptors لفحص وتحويل طلبات أو استجابات HTTP من وإلى الخوادم. يمكن استخدامه للمصادقة أو التخزين المؤقت والعديد من هذه الأشياء ، يمكن إضافة العديد من الاعتراضات وتقييدها لمزيد من المعالجة. في هذه الحالة ، نقوم باعتراض الطلبات وتقديم الاستجابة من ذاكرة التخزين المؤقت إذا كان نص QR هو نفسه.

قم بإنشاء مجلد اعتراض ، ثم قم بإنشاء ملف cache-interceptor.ts :

اعتراض ذاكرة التخزين المؤقت (معاينة كبيرة)

أضف مقتطف الشفرة أدناه إلى الملف:

 import { Injectable } from '@angular/core'; import { HttpInterceptor, HttpResponse, HttpRequest, HttpHandler, HttpEvent } from '@angular/common/http'; import { tap } from 'rxjs/operators'; import { of, Observable } from 'rxjs'; @Injectable({ providedIn: 'root' }) export class RequestCachingService implements HttpInterceptor { private cacheMap = new Map<string, HttpResponse<any>>(); constructor() { } intercept(req: HttpRequest , next: HttpHandler): Observable<HttpEvent<any>> { const cachedResponse = this.cacheMap.get(req.urlWithParams); if (cachedResponse) { return of(cachedResponse); } return next.handle(req).pipe(tap(event => { if (event instanceof HttpResponse) { this.cacheMap.set(req.urlWithParams, event); } })) } } import { Injectable } from '@angular/core'; import { HttpInterceptor, HttpResponse, HttpRequest, HttpHandler, HttpEvent } from '@angular/common/http'; import { tap } from 'rxjs/operators'; import { of, Observable } from 'rxjs'; @Injectable({ providedIn: 'root' }) export class RequestCachingService implements HttpInterceptor { private cacheMap = new Map<string, HttpResponse<any>>(); constructor() { } intercept(req: HttpRequest , next: HttpHandler): Observable<HttpEvent<any>> { const cachedResponse = this.cacheMap.get(req.urlWithParams); if (cachedResponse) { return of(cachedResponse); } return next.handle(req).pipe(tap(event => { if (event instanceof HttpResponse) { this.cacheMap.set(req.urlWithParams, event); } })) } }

في مقتطف الشفرة أعلاه ، لدينا خريطة بالمفتاح هو عنوان URL للطلب والاستجابة هي القيمة. نتحقق مما إذا كان عنوان URL الحالي موجودًا في الخريطة ؛ if it is, then return the response (the rest is handled automatically). If the URL is not in the map, we add it.

We are not done yet. An entry to the app.module.ts is required for its proper functioning. Add the below snippet:

 import { HttpClientModule, HTTP_INTERCEPTORS } from '@angular/common/http'; import { CacheInterceptor } from './interceptor/cache-interceptor'; providers: [ { provide: HTTP_INTERCEPTORS, useClass: CacheInterceptor, multi: true } ],

This adds the caching feature to our application. Let's move on to the third page, the History page.

Adding The History Page

All the saved QR codes will be visible here. To create another component, open terminal type ng gc history and press Enter.

Open history.component.css and add the below code:

 .main-content { padding: 5% 10%; } .truncate { width: 90%; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } .center-img { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); display: flex; flex-direction: column; align-items: center; }

Open history.component.html and replace the content with this:

 <app-header [showBackButton]="showBackButton" [currentTitle]="title" [showHistoryNav]="showHistoryNav"></app-header> <div class="main-content"> <mat-grid-list cols="4" rowHeight="500px" *ngIf="historyList.length > 0"> <mat-grid-tile *ngFor="let qr of historyList"> <mat-card> <img mat-card-image src="{{qr.imageBase64}}"> <mat-card-content> <div class="truncate"> {{qr.text}} </div> </mat-card-content> <mat-card-actions> <button mat-button (click)="share(qr.text)">SHARE</button> <button mat-button color="accent" (click)="delete(qr.text)">DELETE</button> </mat-card-actions> </mat-card> </mat-grid-tile> </mat-grid-list> <div class="center-img" *ngIf="historyList.length == 0"> <img src="../../assets/no-see.png" width="256" height="256"> <span>Nothing to see here</span> </div> </div>

As usual, we have the header component at the top. Then, the rest of the body is a grid list that will show all the saved QR codes as individual mat-card . For the grid view, we are using mat-grid-list from the Angular material library. As per the drill, before we can use it, we have to first add it to the app.module.ts file.

تعمل قائمة شبكة Mat كحاوية بها العديد من الأجزاء الفرعية المتجانبة تسمى mat-grid-tile . في مقتطف HTML أعلاه ، يتم إنشاء كل لوحة باستخدام mat-card باستخدام بعض خصائصها للوضع العام لعناصر واجهة المستخدم الأخرى. يمكننا توفير number of columns و rowHeight ، والذي يستخدم لحساب العرض تلقائيًا. في المقتطف أعلاه ، نقدم كلاً من عدد الأعمدة وقيمة rowHeight .

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

لتنفيذ منطق ملء كل هذه المعلومات ، افتح ملف history.component.ts وأضف المقتطف أدناه إلى فئة HistoryComponent :

 showBackButton = true; title = 'History'; showHistoryNav = false; historyList; constructor(private storageService: StorageutilService, private snackbar: MatSnackBar ) { } ngOnInit() { this.populateHistory(); } private populateHistory() { this.historyList = this.storageService.readAllHistory(); } delete(text: string) { this.storageService.deleteHistory(text); this.populateHistory(); } share(text: string) { this.snackbar.open(text, '', {duration: 2000,}) }

المنطق أعلاه يجلب فقط كل QR المحفوظة ويملأ الصفحة بها. يمكن للمستخدمين حذف رمز الاستجابة السريعة المحفوظ والذي سيؤدي إلى حذف الإدخال من التخزين المحلي.

إذاً هذا ينهي عنصر التاريخ لدينا ... أم يفعل ذلك؟ ما زلنا بحاجة إلى إضافة تعيين المسار لهذا المكون. افتح app-routing.module.ts وأضف تعيينًا لصفحة السجل أيضًا:

 { path: 'history', component: HistoryComponent },

يجب أن تبدو مصفوفة المسار بالكامل كما يلي الآن:

 const routes: Routes = [ { path: '', component: HomeComponent }, { path: 'create', component: CreateQrComponent }, { path: 'history', component: HistoryComponent }, ];

الآن هو الوقت المناسب لتشغيل التطبيق للتحقق من التدفق الكامل ، لذا افتح Terminal واكتب ng serve واضغط على Enter. ثم انتقل إلى localhost:4200 للتحقق من عمل التطبيق.

أضف إلى جيثب

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

  1. افتح جيثب.
  2. قم بإنشاء مستودع جديد.
  3. مستودع GitHub الجديد (معاينة كبيرة)
  4. في VS Code ، استخدم Terminal واتبع المجموعة الأولى من الأوامر المذكورة في دليل البدء السريع لدفع جميع ملفات المشروع.
  5. إضافة مشروع في GitHub (معاينة كبيرة)

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

Netlify والنشر

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

  1. الاشتراك في Netlify.
  2. من لوحة القيادة ، انقر فوق الزر موقع جديد من Git .
  3. موقع Netlify الجديد (معاينة كبيرة)
  4. انقر فوق GitHub في الشاشة التالية.
  5. Netlify حدد مزود بوابة (معاينة كبيرة)
  6. قم بتفويض Netlify لتتمكن من الوصول إلى مستودعات GitHub الخاصة بك.
  7. ترخيص Netlify GitHub (معاينة كبيرة)
  8. ابحث عن مستودع qr الذي تم إنشاؤه حديثًا وحدده.
  9. تحديد مستودع Netlify GitHub (معاينة كبيرة)
  10. يتيح لنا Netlify ، في الخطوة التالية ، اختيار فرع مستودع GitHub لعمليات النشر. عادةً ما يستخدم المرء الفرع master ولكن يمكن أيضًا أن يكون له فرع release منفصل يحتوي فقط على الميزات الثابتة والمتعلقة بالإصدار.
  11. إنشاء ونشر Netlify (معاينة كبيرة)

نظرًا لأن هذا تطبيق ويب Angular ، أضف ng build --prod كأمر build. الدلائل المنشورة ستكون dist/qr كما هو مذكور في ملف angular.json .

مسار البناء الزاوي (معاينة كبيرة)

انقر الآن على زر Deploy site الذي سيطلق بناء مشروع باستخدام الأمر ng build --prod الملف إلى dist/qr .

نظرًا لأننا قدمنا ​​معلومات المسار إلى Netlify ، فسوف يلتقط تلقائيًا الملفات الصحيحة لخدمة تطبيق الويب. يضيف Netlify مجالًا عشوائيًا لتطبيقنا افتراضيًا.

تم نشر موقع Netlify (معاينة كبيرة)

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

مجال مخصص

في الصورة أعلاه ، يظهر عنوان URL لتطبيقنا بينما يتم إنشاء المجال الفرعي بشكل عشوائي. دعونا نغير ذلك.

انقر فوق الزر " Domain settings " ثم في قسم "المجالات المخصصة" ، انقر فوق القائمة المكونة من 3 نقاط وحدد " Edit site name ".

المجال المخصص (معاينة كبيرة)

سيؤدي هذا إلى فتح نافذة منبثقة حيث يمكن إدخال اسم موقع جديد ؛ يجب أن يكون هذا الاسم فريدًا عبر مجال Netlify. أدخل أي اسم موقع متاح وانقر فوق حفظ .

اسم الموقع (معاينة كبيرة)

سيتم الآن تحديث رابط تطبيقنا باسم الموقع الجديد.

اختبار الانقسام

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

الشرط الأساسي لتمكين اختبار الانقسام هو مستودع GitHub بفرعين على الأقل. توجه إلى مستودع التطبيقات في GitHub الذي تم إنشاؤه مسبقًا ، وأنشئ فرعًا a .

إنشاء فرع جديد (معاينة كبيرة)

سيكون للمستودع الآن a master وفرع. يجب تكوين Netlify للقيام بعمليات نشر الفروع ، لذا افتح لوحة معلومات Netlify وانقر على Settings . على الجانب الأيسر ، انقر فوق Build & Deploy ونشر ، ثم Continuous Deployment ، ثم على الجانب الأيمن في قسم Deploy contexts ، انقر فوق Edit settings .

عمليات النشر في الفروع (معاينة كبيرة)

في القسم الفرعي Branch deploys الفرع ، حدد الخيار "دعني أضيف الفروع الفردية" ، وأدخل أسماء الفروع واحفظها.

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

الآن ، انقر فوق خيار علامة التبويب Split Testing في أعلى الصفحة. سيتم تقديم تكوينات اختبار الانقسام هنا.

اختبار الانقسام (معاينة كبيرة)

يمكننا تحديد الفرع (بخلاف فرع الإنتاج) - في هذه الحالة a . يمكننا أيضًا اللعب مع إعدادات تقسيم حركة المرور. بناءً على النسبة المئوية لحركة المرور التي تم تخصيصها لكل فرع ، ستعيد Netlify توجيه بعض المستخدمين إلى التطبيق المنشور باستخدام الفرع والآخرين a الفرع master . بعد التكوين ، انقر فوق الزر Start test لتمكين تقسيم حركة المرور.

نصيحة : قد لا يتعرف Netlify على أن مستودع GitHub المتصل به أكثر من فرع وقد يعطي هذا الخطأ:

خطأ في اختبار الانقسام (معاينة كبيرة)

لحل هذه المشكلة ، ما عليك سوى إعادة الاتصال بالمستودع من خيارات Build & Deploy .

يوفر Netlify الكثير من الميزات الأخرى أيضًا. لقد استعرضنا للتو بعض ميزاته المفيدة لإثبات سهولة تكوين جوانب مختلفة من Netlify.

هذا يقودنا إلى نهاية رحلتنا. لقد نجحنا في إنشاء تصميم Angular Material استنادًا إلى تطبيق ويب ونشره على Netlify.

خاتمة

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

قراءة متعمقة

  • العمارة الزاويّة
  • المزيد من مكونات المواد الزاوي
  • المزيد حول ميزات Netlify