أخف وأسرع - دليل لإطار العمل الرقيق
نشرت: 2022-03-11أصبحت تطبيقات الويب أكثر شيوعًا يومًا بعد يوم. إنه عالم متنامٍ يختاره الناس بسبب بساطته وسرعته وتوافره عبر الأنظمة الأساسية. لقد لعبت تطبيقات الصفحة الواحدة (SPA) دورًا كبيرًا في هذه العملية. تساعد أطر العمل مثل Angular و Vue.js و React المطورين على تقديم أفضل تجربة للمستخدم في فترة قصيرة مما يجعل الشفرة قابلة للدعم وقابلة للتمديد. ظلت هذه الأدوات لفترة طويلة الأكثر شيوعًا في هذا المجال ، مع العديد من المزايا على الحزم التي تم إنشاؤها حديثًا. لقد شعرت وكأنها احتكار القلة في عالم SPA. ومع ذلك ، يمكن لمجموعة من المطورين التطلعيين الذين يستهدفون هذا السوق الدخول مع منافس جاد - Svelte.
Svelte هو نهج جديد لبناء واجهات المستخدم. دعنا نتعمق ونستكشف ما الذي يجعله جديدًا للغاية من خلال إنشاء نموذج تسجيل دخول مشترك.
بنيان
تم تصميم Svelte ليكون أسرع من أي مكتبة أخرى. يتم الوصول إليه عن طريق تغيير خطوة تحميل إطار عمل لبناء DOM افتراضي. بدلاً من استخدام أداة أثناء عملية التشغيل ، يتم تجميعها إلى Vanilla JS في مرحلة البناء ، لذلك لا يتطلب التطبيق أي تبعيات للبدء.
ممشوق | مكتبات SPA الأخرى (React ، Vue.js ، Angular ، إلخ.) |
---|---|
1. افتح موقعًا إلكترونيًا | 1. افتح موقعًا إلكترونيًا |
يصف الجدول أعلاه سبب كون Svelte فائزًا مطلقًا في أداء بدء التشغيل. لا يتم الحصول عليها من خلال أي نوع من التحسين ولكن باستخدام مترجم JavaScript في المتصفح المتاح بدلاً من مترجم جانبي.
تثبيت
التثبيت الرقيق سهل للغاية ، مما يجعل استخدامه ممتعًا للغاية. الخطوة الأولى هي تنزيل نموذج المشروع:
npx degit sveltejs/template svelte-login-form
يعني إكمال الأمر أعلاه أن لدينا قالب مشروع Svelte. إنه فارغ في الوقت الحالي ولم يتم تثبيت حزم NPM المطلوبة بعد. دعونا نصلح ذلك.
cd svelte-login-form npm install
الآن التطبيق جاهز للبدء باستخدام الأمر التالي:
npm run dev
هيكل
قد يحتوي أي مكون من مكونات Svelte على الأقسام التالية:
- النصي
- أسلوب
- قالب
لنلقِ نظرة على المثال الموجود في ملف src/App.svelte
.
<script> export let name; </script> <style> h1 { color: purple; } </style> <h1>{name}</h1>
يحتوي الكود أعلاه على ثلاثة أقسام بالضبط:
علامة
script
، وهي عبارة عن كتلة JavaScript اختيارية بها إعلانات المتغيرات والوظائف التي يجب استخدامها داخل المكون.علامة
style
، وهي كتلة اختيارية أخرى. إنها تشبه إلى حد كبير علامة نمط HTML الشائعة باستثناء اختلاف واحد مهم. يقتصر نطاق القواعد الموضحة داخل هذه الكتلة على هذا المكون فقط. تطبيق نمط على عنصرp
لن يؤثر على كل فقرات الصفحة. إنه أمر رائع لأنك لست مضطرًا إلى ابتكار أسماء فئات ولن تتخطى قاعدة أخرى عن طريق الخطأ.الكتلة الأخيرة والوحيدة المطلوبة هي كتلة قالب - في هذه الحالة ، علامة
h1
. إنه عرض تقديمي / عرض للمكون الخاص بك. إنه مرتبط بشدة بكتل الأنماط والنصوص لأنها تحدد كيف سيتم تصميم العرض وكيف سيتصرف.
Svelte هي مكتبة تحاول إدخال نمطية إلى لعبة الواجهة الأمامية. إنها تحافظ على هذه الوحدة ليس فقط في فصل المكونات المختلفة ولكن أيضًا في عزل المنطق والعرض والقالب.
بالعودة إلى نموذج تسجيل الدخول الذي نقوم ببنائه ، لنقم بإنشاء ملف جديد LoginForm.svelte
داخل مجلد src
بالمحتوى التالي:
<style> form { background: #fff; padding: 50px; width: 250px; height: 400px; display: flex; flex-direction: column; justify-content: center; align-items: center; box-shadow: 0px 20px 14px 8px rgba(0, 0, 0, 0.58); } label { margin: 10px 0; align-self: flex-start; font-weight: 500; } input { border: none; border-bottom: 1px solid #ccc; margin-bottom: 20px; transition: all 300ms ease-in-out; width: 100%; } input:focus { outline: 0; border-bottom: 1px solid #666; } button { margin-top: 20px; background: black; color: white; padding: 10px 0; width: 200px; border-radius: 25px; text-transform: uppercase; font-weight: bold; cursor: pointer; transition: all 300ms ease-in-out; } button:hover { transform: translateY(-2.5px); box-shadow: 0px 1px 10px 0px rgba(0, 0, 0, 0.58); } h1 { margin: 10px 20px 30px 20px; font-size: 40px; } </style> <form> <h1></h1> <label>Email</label> <input name="email" placeholder="[email protected]" /> <label>Password</label> <input name="password" type="password" placeholder="password" /> <button type="submit">Log in </button> </form>
إنه مكون ذو طراز غبي سنجعله أكثر ذكاءً لاحقًا. لرؤية هذا المكون على موقعنا ، يجب أن نعرضه داخل مكون الجذر - التطبيق. دعنا نذهب ونقوم بتعديل src/App.svelte
بحيث تبدو كالتالي:
<script> import LoginForm from "./LoginForm.svelte"; </script> <style> section { height: 100vh; width: 100%; display: flex; justify-content: center; align-items: center; background: linear-gradient(to right, #cd76e2, #e358ab); } </style> <section> <LoginForm /> </section>
إذا تم تنفيذ كل شيء بشكل صحيح وكان التطبيق لا يزال قيد التشغيل ، فسيظهر نموذجنا على localhost:5000
. دعنا نرفع مستوى مهاراتنا Svelte من خلال جعل النموذج أكثر ذكاءً.
الذهاب الدولة
يمكن أن يكون لأي مكون في Svelte حالته. الحالة هي متغير خاص أو مجموعة متغيرات خاصة يمكن استخدامها داخل القالب. لماذا أقول "خاص"؟ عندما يتم تغيير هذا المتغير ، يتم إخطار القالب به ويعرض المحتوى بأحدث حالة. هذا يسمح للتطبيق بالتفاعل مع تفاعلات المستخدم بسرعة كبيرة.
سنعلن عن متغيرات حالة email
password
حيث سيتم تخزين قيم النموذج للحقول المناسبة. هذا يعني أن متغيرات email
password
الخاصة بنا ستكون دائمًا متزامنة مع قيم النموذج ، لذلك سنكون مستعدين لإرسال هذه القيم في أي وقت دون خوف من وجود أي اختلافات بين قيم الإرسال والقيم الفعلية في النموذج.
<script> let email = ""; let password = ""; let isLoading = false; const handleSubmit = () => { isLoading = true; // Simulate network request setTimeout(() => { isLoading = false; // Authorize the user }, 1000); }; </script> <style> /* Style is unchanged */ </style> <form on:submit|preventDefault={handleSubmit}> <h1></h1> <label>Email</label> <input name="email" placeholder="[email protected]" bind:value={email} /> <label>Password</label> <input name="password" type="password" bind:value={password} /> {#if isLoading}Logging in...{:else}Log in {/if} </form>
تبدو متغيرات الحالة مثل متغيرات JavaScript الشائعة ولكن لجعلها متزامنة مع قيم النموذج (اربطها بحقول النموذج) ، من الضروري استخدام توجيه bind:value
. هناك أيضًا بعض الأشياء غير المألوفة:
on:submit|preventDefault
اختصارًا لمنع سلوك الأحداث الافتراضية. إنها أكثر راحة بهذه الطريقة من الاضطرار إلى كتابةe.preventDefault()
في كل مرة.{#if isLoading}Logging in...{:else}Log in {/if}
هو جزء من بنية نموذج Svelte. نظرًا لعدم وجود JS في كتلة القالب ، فهناك بناء جملة خاص لاستخدام ifs ، والحلقات ، وما إلى ذلك.
أخيرًا ، دعنا نستخدم الخيارات المتاحة باستخدام الحالة لإضافة التحقق من صحة النموذج الخاص بنا. يمكن تحقيق ذلك عن طريق إنشاء errors
متغيرة أخرى للحالة ، والتي سيتم ملؤها بالأخطاء عند تقديم النموذج بقيم غير صالحة.
<script> let email = ""; let password = ""; let isLoading = false; let errors = {}; const handleSubmit = () => { errors = {}; if (email.length === 0) { errors.email = "Field should not be empty"; } if (password.length === 0) { errors.password = "Field should not be empty"; } if (Object.keys(errors).length === 0) { isLoading = true; // Simulate network request setTimeout(() => { isLoading = false; // Authorize the user }, 1000); } }; </script> <style> // Previous styles unchanged .errors { list-style-type: none; padding: 10px; margin: 0; border: 2px solid #be6283; color: #be6283; background: rgba(190, 98, 131, 0.3); } </style> <form on:submit|preventDefault={handleSubmit}> <h1></h1> <label>Email</label> <input name="email" placeholder="[email protected]" bind:value={email} /> <label>Password</label> <input name="password" type="password" bind:value={password} /> <button type="submit"> {#if isLoading}Logging in...{:else}Log in {/if} </button> {#if Object.keys(errors).length > 0} <ul class="errors"> {#each Object.keys(errors) as field} <li>{field}: {errors[field]}</li> {/each} </ul> {/if} </form>

اكتمل النموذج تقريبًا. الشيء الوحيد المتبقي هو رسالة نجاح عند المصادقة الناجحة.

لنقم بإنشاء متغير حالة لتتبع عمليات الإرسال الناجحة وهو false
افتراضيًا. بعد الإرسال الناجح للنموذج ، يجب تعيين قيمة هذا المتغير على " true
".
let isSuccess = false;
يجب أيضًا تغيير الوظيفة التي تتعامل مع إرسال النموذج لتتبع منطق isSuccess
هو النجاح بعد عملية ناجحة.
const handleSubmit = () => { errors = {}; if (email.length === 0) { errors.email = "Field should not be empty"; } if (password.length === 0) { errors.password = "Field should not be empty"; } if (Object.keys(errors).length === 0) { isLoading = true; // Simulate network request setTimeout(() => { isLoading = false; isSuccess = true; // Authorize the user }, 1000); } };
هذا التعديل يجعل النموذج ينتقل إلى حالة النجاح بمجرد اكتمال الإرسال.
ولكن إذا قمت بفحص خادم التطوير الخاص بك ، فلن تجد أي تغييرات في سلوك النموذج. لقد غيرنا الكود لكننا لم نلمس القالب بعد. نحتاج إلى إضافة تعليمات إلى القالب لإظهار رسالة نجاح عندما يقوم المستخدم بتسجيل الدخول بنجاح. تسمح لنا بنية قالب Svelte بتنفيذ ذلك بسهولة:
<form on:submit|preventDefault={handleSubmit}> {#if isSuccess} <div class="success"> <br /> You've been successfully logged in. </div> {:else} <h1></h1> <label>Email</label> <input name="email" placeholder="[email protected]" bind:value={email} /> <label>Password</label> <input name="password" type="password" bind:value={password} /> <button type="submit"> {#if isLoading}Logging in...{:else}Log in {/if} </button> {#if Object.keys(errors).length > 0} <ul class="errors"> {#each Object.keys(errors) as field} <li>{field}: {errors[field]}</li> {/each} </ul> {/if} {/if} </form>
الملخص مع الخصائص
لقد قمنا بفرز كل شيء عن حالة المكون الداخلي. حان الوقت الآن لتصفح التبعيات الخارجية التي تسمى الخصائص ، أو "الدعائم". الدعائم هي مدخلات أو وسيطات يتم تمريرها إلى المكون لوصف المكون الذي يجب أن يظهر أو كيف يجب أن يتصرف المكون.
يشبه إعلان الخاصية الحالة ، باستثناء export
الكلمة الأساسية.
<script> export let answer; </script> <p>The answer is {answer}</p>
<script> import Nested from './Nested.svelte'; </script> <Nested answer={42}/>
الأمر كله يتعلق بالخصائص. أعلن وتمرير - كل ما تحتاج إلى معرفته لاستخدام الدعائم.
ولكن كيف تنطبق هذه الخصائص على مكون نموذج تسجيل الدخول؟ يمكن أن تجعل الدعائم نموذج تسجيل الدخول الخاص بنا أكثر عمومية عن طريق استخراج وظيفة الإرسال في خاصية. سيسمح لك باستخدام هذا المكون مع أي إجراء إرسال تحتاجه (طلب إلى خادم اختبار ، أو طلب إلى خادم فعلي ، وما إلى ذلك). سيُطلق على هذه الخاصية اسم submit
وستكون دالة تُرجع وعدًا تم حله إذا نجح إجراء الإرسال ووعد مرفوض إذا كان هناك خطأ. دعنا نعلن عن الخاصية بالمثال الموضح أعلاه:
export let submit;
يجب أيضًا تحرير معالج الإرسال الموجود داخل نموذج تسجيل الدخول لاستخدام خاصية submit
الجديدة.
const handleSubmit = () => { errors = {}; if (email.length === 0) { errors.email = "Field should not be empty"; } if (password.length === 0) { errors.password = "Field should not be empty"; } if (Object.keys(errors).length === 0) { isLoading = true; submit({ email, password }) .then(() => { isSuccess = true; isLoading = false; }) .catch(err => { errors.server = err; isLoading = false; }); } };
يبدو أن المكون جاهز. ومع ذلك ، إذا عدت إلى النموذج وحاولت إرساله ، فستلاحظ أن حالة الزر لم تتغير من التحميل. أيضًا ، هناك استثناء في وحدة التحكم: خطأ في Uncaught TypeError: submit is not a function
. بالطبع ، أعلنا عن الدعامة لكننا نسينا تمريرها. دعنا نعلن عن وظيفة في مكون التطبيق ونمررها إلى نموذج تسجيل الدخول.
const submit = ({ email, password }) => new Promise((resolve, reject) => setTimeout(resolve, 1000));
<section> <LoginForm submit={submit} /> </section>
الآن يعمل النموذج على النحو المنشود. يمكنه عرض الأخطاء وإبلاغ المستخدم إذا كان تسجيل الدخول ناجحًا.

تقاسم السياق
يبدو أنه تم سرد كل ما هو ضروري لإنشاء تطبيق. مع الخصائص والحالة الداخلية ، نحن على استعداد للذهاب. هذا صحيح جزئيًا فقط. هاتان النقطتان العامتان تجعلان من الممكن تصميم SPA عالية التعقيد. ومع ذلك ، إذا حاولت مشاركة البيانات بين العديد من المكونات المختلفة ، فستجد ذلك صعبًا للغاية.
أبسط مثال على ذلك هو وجود متغير user
يمكن الوصول إليه عالميًا. يجب أن تغير الكثير من المكونات سلوكها المرتبط بالمستخدم ، اعتمادًا على دور المستخدم ، وعمره ، وحالته ، وما إلى ذلك. ومع ذلك ، فليس من الجاف أن نكرر أنفسنا عن طريق تمرير المستخدم إلى كل مكون في التطبيق باستخدام الدعائم.
Svelte لديه حل لهذا: سياق API.
توفر واجهة برمجة تطبيقات السياق آلية للمكونات "للتحدث" مع بعضها البعض دون تمرير البيانات والوظائف كدعامات أو إرسال الكثير من الأحداث. إنها ميزة متقدمة ولكنها مفيدة.
دعنا نضيف سياق المستخدم إلى نموذج تسجيل الدخول الذي نصممه. قم بإنشاء ملف userContext.js
داخل مجلد src
بالمحتوى التالي:
export const key = "userContext"; export const initialValue = null;
key
هو معرّف فريد للسياق حيث قد يحتوي التطبيق على عدد غير محدود من السياقات المختلفة التي يجب أن تظل قابلة للوصول. initialValue
هي مجرد قيمة افتراضية للسياق قبل تعيينه.
الخطوة التالية هي إضافة السياق إلى تطبيقنا. انتقل إلى ملف App.svelte
استيراد:
import { onMount, setContext } from "svelte"; import { key as userContextKey, initialValue as userContextInitialValue } from "./userContext";
بالنظر إلى الكود أعلاه ، قد تتساءل عما نستورده من الحزمة svelte
. onMount
هي وظيفة مساعدة تتطلب وظيفة رد كوسيطة. سيتم تنفيذ رد الاتصال هذا عندما يتم تركيب المكون الحالي (في بداية تحميل المكون). setContext
هي دالة ضبط لسياق ما. يتطلب مفتاح السياق وقيمة جديدة كوسيطاته.
دعنا نستخدم وظيفة onMount
لتعيين القيمة الافتراضية للسياق:
onMount(() => { setContext(userContextKey, userContextInitialValue); });
وتعديل وظيفة submit
لتعيين سياق المستخدم:
const submit = ({ email, password }) => new Promise((resolve, reject) => { setTimeout(() => { setContext(userContextKey, { name: "Foo", lastName: "Bar", email: "[email protected]" }); resolve(); }, 1000); });
هذا هو. سيؤدي الإرسال الناجح إلى تغيير سياق المستخدم إلى كائن مستخدم مزيف يمكن الوصول إليه عن طريق getContext
للحصول على سياق:
<script> import { getContext } from 'svelte'; import { key as userContextKey } from "./userContext"; const user = getContext(key); </script>
ملخص
Svelte هي أداة قوية قادرة على الأداء العالي ومع واجهة برمجة تطبيقات مرنة. إلى جانب الأساسيات التي تم تناولها في هذا المنشور ، تتمتع Svelte بالميزات التالية خارج الصندوق:
- التصريحات والبيانات التفاعلية
- في انتظار كتل القالب
- البعد ملزم
- متجر عالمي مثل Redux
- مساعدو الرسوم المتحركة والانتقال
- مساعد التصحيح
باختصار ، Svelte هي مكتبة رائعة تلبي جميع احتياجات بناء SPA ، وأكثر من ذلك. يمكنها التنافس مع أكبر اللاعبين في السوق ، وحتى الفوز. ما يمكن أن تستخدمه الآن ، على الرغم من ذلك ، هو الدعم في مجتمع مطوري الواجهة الأمامية.
ملاحظة: يمكن العثور على جميع الأكواد في هذه المقالة في مستودع جيثب teimurjan/svelte-login-form
. العرض التوضيحي لنموذج تسجيل الدخول متاح هنا.