معالج SASS/SCSS

@use و @forward: نظام الوحدات الحديث

25 دقيقة الدرس 8 من 30

@use و @forward: نظام الوحدات الحديث

تمثل توجيهات @use و @forward نظام الوحدات الحديث في SASS، المصمم ليحل محل توجيه @import المهمل. يحل هذا النظام الجديد العديد من المشاكل مع @import من خلال إدخال مساحات الأسماء، ومنع الاستيرادات المكررة، وتوفير تحكم أفضل في ما يتم عرضه من كل ملف.

لماذا يحل @use محل @import

تم تقديم توجيه @use لمعالجة المشاكل الأساسية مع @import:

  • مساحات الأسماء: يقوم @use تلقائياً بوضع الأعضاء المستوردة في مساحات أسماء، مما يمنع تعارضات التسمية
  • لا استيرادات مكررة: يتم تحميل الملف مرة واحدة فقط، بغض النظر عن عدد مرات استخدامه
  • تبعيات صريحة: يمكنك رؤية بالضبط من أين يأتي كل متغير/خلطة
  • أعضاء خاصة: المتغيرات التي تبدأ بـ - أو _ خاصة بالوحدة
  • أداء أفضل: يتم تحميل الملفات مرة واحدة فقط وتخزينها مؤقتاً
مهم: @use هو الطريقة الموصى بها لتحميل وحدات SASS. @import مهمل وسيتم إزالته في SASS 3.0. يجب على جميع المشاريع الجديدة استخدام @use.

صيغة @use الأساسية

يقوم توجيه @use بتحميل ملف SASS آخر كوحدة. بشكل افتراضي، يتم وضع الأعضاء (المتغيرات، الخلطات، الدوال) في مساحات أسماء باستخدام اسم الملف.

مثال بسيط على @use

// _colors.scss
$primary: #3498db;
$secondary: #2ecc71;
$text: #333;

// main.scss
@use "colors";

body {
  color: colors.$text;
  background: colors.$primary;
}

h1 {
  color: colors.$secondary;
}

// CSS المترجم
body {
  color: #333;
  background: #3498db;
}

h1 {
  color: #2ecc71;
}
صيغة مساحة الاسم: للوصول إلى الأعضاء من وحدة مستخدمة، استخدم الصيغة: namespace.member (مثل colors.$primary، math.round()، mixins.flex-center())

الوصول إلى أعضاء الوحدة

عندما تقوم بـ @use لوحدة، تصل إلى متغيراتها وخلطاتها ودوالها من خلال مساحة الاسم الخاصة بها. يتم اشتقاق مساحة الاسم من المكون الأخير من URL الوحدة (اسم الملف بدون مسار الدليل والامتداد).

الوصول إلى أنواع أعضاء مختلفة

// _variables.scss
$font-size: 16px;
$line-height: 1.6;

// _mixins.scss
@mixin flex-center {
  display: flex;
  justify-content: center;
  align-items: center;
}

@mixin button-variant($bg-color) {
  background: $bg-color;
  color: white;
  &:hover {
    background: darken($bg-color, 10%);
  }
}

// _functions.scss
@function px-to-rem($px) {
  @return $px / 16 * 1rem;
}

// main.scss
@use "variables";
@use "mixins";
@use "functions";

body {
  font-size: variables.$font-size;
  line-height: variables.$line-height;
}

.container {
  @include mixins.flex-center;
  padding: functions.px-to-rem(20);
}

.button {
  @include mixins.button-variant(blue);
}

مساحات أسماء مخصصة باستخدام "as"

إذا لم تعجبك مساحة الاسم الافتراضية، يمكنك تخصيصها باستخدام الكلمة الرئيسية "as". هذا مفيد لتقصير أسماء الوحدات الطويلة أو تجنب تعارضات مساحات الأسماء.

مثال على مساحة الاسم المخصصة

// _typography-config.scss
$heading-font: "Georgia", serif;
$body-font: "Arial", sans-serif;

// main.scss - مساحة الاسم الافتراضية
@use "typography-config";
body {
  font-family: typography-config.$body-font;
}

// main.scss - مساحة الاسم المخصصة
@use "typography-config" as typo;
body {
  font-family: typo.$body-font;
}

// main.scss - مساحة اسم قصيرة جداً
@use "typography-config" as t;
body {
  font-family: t.$body-font;
}

مساحة الاسم الخاصة * (استخدم باعتدال)

يمكنك استخدام "as *" لتحميل وحدة بدون مساحة اسم، مما يجعل أعضائها متاحة مباشرة. ومع ذلك، يجب استخدام هذا باعتدال لأنه يتعارض مع غرض مساحات الأسماء.

التحميل بدون مساحة اسم

// _variables.scss
$primary: blue;
$secondary: green;

// main.scss
@use "variables" as *;

// الآن يمكنك استخدام المتغيرات مباشرة بدون مساحة اسم
body {
  color: $primary;
  background: $secondary;
}

// هذا مشابه لـ @import، ولكن لا يزال له فوائد:
// - يتم تحميل الملف مرة واحدة فقط
// - الأعضاء الخاصة (التي تبدأ بـ -) لا تزال مخفية
تحذير: استخدام "as *" يزيل فوائد مساحات الأسماء ويمكن أن يؤدي إلى تعارضات التسمية. استخدمه فقط للوحدات مثل المتغيرات حيث تكون واثقاً من عدم وجود تعارضات، وتريد صيغة أنظف.

الأعضاء الخاصة

في نظام وحدة @use، الأعضاء (المتغيرات، الخلطات، الدوال) التي تبدأ أسماؤها إما بشرطة (-) أو شرطة سفلية (_) تعتبر خاصة بالوحدة. لا يمكن الوصول إليها من خارج الوحدة.

مثال على الأعضاء الخاصة

// _config.scss
// متغير عام
$primary-color: blue;

// متغير خاص (يبدأ بـ -)
$-internal-padding: 10px;

// متغير خاص (يبدأ بـ _)
$_debug-mode: false;

// خلطة خاصة
@mixin -helper-mixin {
  padding: $-internal-padding;
}

// خلطة عامة تستخدم أعضاء خاصة
@mixin component {
  @include -helper-mixin;
  color: $primary-color;
}

// main.scss
@use "config";

.element {
  // هذا يعمل - متغير عام
  color: config.$primary-color;

  // هذا يعمل - خلطة عامة
  @include config.component;

  // خطأ - متغير خاص غير قابل للوصول
  // padding: config.$-internal-padding;

  // خطأ - خلطة خاصة غير قابلة للوصول
  // @include config.-helper-mixin;
}
أفضل ممارسة: استخدم الأعضاء الخاصة لتفاصيل التنفيذ الداخلية التي لا ينبغي استخدامها خارج الوحدة. هذا ينشئ واجهات برمجة تطبيقات عامة واضحة لوحداتك ويمنع الاقتران الوثيق.

تكوين الوحدات باستخدام "with"

واحدة من أقوى ميزات @use هي القدرة على تكوين وحدة قبل تحميلها. يمكنك تجاوز المتغيرات المعرفة باستخدام !default في الوحدة.

تكوين الوحدة

// _library.scss
$color: blue !default;
$size: 16px !default;
$border-radius: 4px !default;

.widget {
  color: $color;
  font-size: $size;
  border-radius: $border-radius;
}

// main.scss
@use "library" with (
  $color: red,
  $size: 18px,
  $border-radius: 8px
);

// سيستخدم صنف .widget الآن:
// color: red
// font-size: 18px
// border-radius: 8px
علامة !default: يجب تعريف المتغيرات في الوحدة باستخدام !default لتكون قابلة للتكوين. تعني علامة !default "استخدم هذه القيمة إذا لم يتم تعيين المتغير بعد."

مثال تكوين متقدم

// _button-system.scss
$btn-bg: blue !default;
$btn-color: white !default;
$btn-padding: 10px 20px !default;
$btn-border-radius: 4px !default;
$btn-hover-darken: 10% !default;

@mixin button-base {
  display: inline-block;
  padding: $btn-padding;
  background: $btn-bg;
  color: $btn-color;
  border: none;
  border-radius: $btn-border-radius;
  cursor: pointer;

  &:hover {
    background: darken($btn-bg, $btn-hover-darken);
  }
}

// theme-1.scss
@use "button-system" with (
  $btn-bg: #3498db,
  $btn-border-radius: 20px
);

.button {
  @include button-system.button-base;
}

// theme-2.scss
@use "button-system" with (
  $btn-bg: #e74c3c,
  $btn-color: white,
  $btn-padding: 15px 30px,
  $btn-hover-darken: 15%
);

.button {
  @include button-system.button-base;
}

توجيه @forward

يقوم توجيه @forward بتحميل وحدة وجعل أعضائها متاحة للملفات التي تحمل ملفك. هذا مفيد لإنشاء ملفات "فهرس" تعيد تصدير وحدات متعددة، أو لإنشاء واجهة برمجة تطبيقات عامة لمكتبة.

@forward الأساسي

// _colors.scss
$primary: blue;
$secondary: green;

// _typography.scss
$font-main: Arial, sans-serif;
$font-size: 16px;

// _index.scss (يجمع ملفات متعددة)
@forward "colors";
@forward "typography";

// main.scss
@use "index";

body {
  color: index.$primary;          // من colors
  font-family: index.$font-main;  // من typography
  font-size: index.$font-size;    // من typography
}

التحكم في الرؤية باستخدام show و hide

يمكنك التحكم في الأعضاء الذين يتم إعادة توجيههم باستخدام الكلمات الرئيسية "show" و "hide". يتيح لك هذا إنشاء صادرات انتقائية وإخفاء تفاصيل التنفيذ.

استخدام show

// _internal.scss
$public-var: red;
$internal-var: blue;
$debug-var: green;

@mixin public-mixin { }
@mixin internal-mixin { }

// _api.scss (إعادة توجيه الأعضاء العامة فقط)
@forward "internal" show $public-var, public-mixin;

// main.scss
@use "api";

.element {
  // هذا يعمل
  color: api.$public-var;
  @include api.public-mixin;

  // هذه لا تعمل - لم يتم إعادة توجيهها
  // color: api.$internal-var;
  // @include api.internal-mixin;
}

استخدام hide

// _config.scss
$primary: blue;
$secondary: green;
$internal-spacing: 8px;
$debug-mode: false;

// _public-api.scss (إخفاء الأعضاء الداخلية)
@forward "config" hide $internal-spacing, $debug-mode;

// main.scss
@use "public-api";

.element {
  // هذه تعمل
  color: public-api.$primary;
  background: public-api.$secondary;

  // هذه لا تعمل - مخفية
  // padding: public-api.$internal-spacing;
  // display: if(public-api.$debug-mode, block, none);
}

إضافة بادئات باستخدام as

عند إعادة التوجيه، يمكنك إضافة بادئة لجميع الأعضاء المعاد توجيههم. هذا مفيد لإنشاء مجموعات وحدات ذات مساحات أسماء.

مثال البادئة

// _buttons.scss
$bg-color: blue;
@mixin style { }

// _inputs.scss
$bg-color: white;
@mixin style { }

// _forms-index.scss
@forward "buttons" as btn-*;
@forward "inputs" as input-*;

// main.scss
@use "forms-index" as forms;

.button {
  background: forms.$btn-bg-color;   // من buttons
  @include forms.btn-style;
}

.input {
  background: forms.$input-bg-color;  // من inputs
  @include forms.input-style;
}

بناء ملف فهرس

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

نمط الفهرس الكامل

// بنية الدليل:
// design-system/
//   ├── _colors.scss
//   ├── _typography.scss
//   ├── _spacing.scss
//   ├── _buttons.scss
//   ├── _cards.scss
//   └── _index.scss

// design-system/_colors.scss
$primary: #3498db !default;
$secondary: #2ecc71 !default;

// design-system/_typography.scss
$font-base: "Arial", sans-serif !default;
$font-size: 16px !default;

// design-system/_spacing.scss
$unit: 8px !default;
$small: $unit !default;
$medium: $unit * 2 !default;
$large: $unit * 3 !default;

// design-system/_buttons.scss
@use "colors";
@use "spacing";

.btn {
  padding: spacing.$medium;
  background: colors.$primary;
}

// design-system/_cards.scss
@use "colors";
@use "spacing";

.card {
  padding: spacing.$large;
  border: 1px solid colors.$primary;
}

// design-system/_index.scss
@forward "colors";
@forward "typography";
@forward "spacing";
@forward "buttons";
@forward "cards";

// main.scss في مشروعك
@use "design-system" with (
  $primary: #e74c3c,
  $font-size: 18px,
  $unit: 10px
);

// الآن design-system.$primary وما إلى ذلك متاحة
body {
  font-size: design-system.$font-size;
  color: design-system.$primary;
}

الترحيل من @import إلى @use/@forward

يتطلب الترحيل من @import إلى @use بعض التغييرات في بنية الكود الخاص بك، لكن الفوائد تستحق ذلك.

قبل (مع @import)

// _variables.scss
$primary: blue;

// _mixins.scss
@import "variables";

@mixin button {
  background: $primary;
}

// main.scss
@import "variables";
@import "mixins";

.btn {
  @include button;
  color: $primary;
}

بعد (مع @use)

// _variables.scss
$primary: blue;

// _mixins.scss
@use "variables";

@mixin button {
  background: variables.$primary;
}

// main.scss
@use "variables";
@use "mixins";

.btn {
  @include mixins.button;
  color: variables.$primary;
}

// أو مع "as *" للمتغيرات:
@use "variables" as *;
@use "mixins";

.btn {
  @include mixins.button;
  color: $primary;  // لا حاجة لمساحة الاسم
}
استراتيجية الترحيل:
  1. ابدأ بالوحدات الطرفية (تلك التي لا تستورد أي شيء)
  2. حول @import إلى @use، مضيفاً مساحات الأسماء
  3. قم بتحديث جميع المراجع لاستخدام صيغة مساحات الأسماء
  4. أنشئ ملفات فهرس باستخدام @forward لمجموعات الوحدات
  5. ضع علامة على المتغيرات القابلة للتكوين باستخدام !default
  6. اجعل المساعدين الداخليين خاصين باستخدام بادئة - أو _

أفضل ممارسات نظام الوحدات

أفضل الممارسات:
  • استخدم مساحات أسماء ذات معنى: احتفظ بالأسماء الافتراضية أو استخدم أسماء مستعارة قصيرة وواضحة
  • قم بالتكوين في الأعلى: استخدم جمل "with" في بيان @use
  • ضع علامة على كل شيء قابل للتكوين: استخدم !default على المتغيرات التي قد يرغب المستخدمون في تجاوزها
  • إخفاء تفاصيل التنفيذ: استخدم بادئة - أو _ للأعضاء الخاصة
  • إنشاء ملفات فهرس: استخدم @forward لإنشاء نقاط دخول واحدة
  • تجنب "as *": استخدم مساحات أسماء صريحة باستثناء ملفات المتغيرات النقية
  • وثق وحداتك: أضف تعليقات تشرح ما هو عام وقابل للتكوين

وحدة منظمة جيداً

// _button-system.scss
// واجهة برمجة التطبيقات العامة لمكونات الأزرار
//
// المتغيرات القابلة للتكوين:
//   $background: لون الخلفية للأزرار
//   $text-color: لون النص للأزرار
//   $padding: الحشوة الداخلية
//
// الخلطات العامة:
//   button-base: تنسيق الأزرار الأساسي
//   button-variant($color): إنشاء شكل لون
//
// مثال:
//   @use "button-system" with ($background: red);
//   .btn { @include button-system.button-base; }

// التكوين (عام، قابل للتجاوز)
$background: blue !default;
$text-color: white !default;
$padding: 10px 20px !default;
$border-radius: 4px !default;

// مساعدون خاصون
$-transition-speed: 0.3s;

@mixin -hover-effect {
  transform: translateY(-2px);
  box-shadow: 0 4px 8px rgba(0,0,0,0.15);
}

// واجهة برمجة التطبيقات العامة
@mixin button-base {
  display: inline-block;
  padding: $padding;
  background: $background;
  color: $text-color;
  border-radius: $border-radius;
  border: none;
  cursor: pointer;
  transition: all $-transition-speed;

  &:hover {
    @include -hover-effect;
  }
}

@mixin button-variant($color) {
  background: $color;

  &:hover {
    background: darken($color, 10%);
  }
}

تمرين 1: التحويل من @import إلى @use

حول هذا الكود القائم على @import لاستخدام @use:

// _variables.scss
$primary: blue;
$font-size: 16px;

// _helpers.scss
@import "variables";
@mixin center { display: flex; justify-content: center; }

// main.scss
@import "variables";
@import "helpers";
body { font-size: $primary; @include center; }

أعد الكتابة باستخدام @use مع مساحات الأسماء المناسبة. ضع في اعتبارك استخدام "as *" للمتغيرات إذا كان ذلك مناسباً.

تمرين 2: إنشاء نظام سمة قابل للتكوين

قم ببناء نظام سمة باستخدام @use و @forward:

  • أنشئ _theme.scss مع متغيرات اللون (جميعها مع !default)
  • أنشئ _components.scss الذي يستخدم ألوان السمة
  • أنشئ _index.scss الذي يعيد توجيه كلا الملفين
  • أنشئ theme-light.scss و theme-dark.scss اللذين يكونان السمة بشكل مختلف

تمرين 3: بناء فهرس نظام التصميم

أنشئ نظام تصميم مع وحدات متعددة:

  • _colors.scss، _typography.scss، _spacing.scss (التكوين)
  • _buttons.scss، _cards.scss، _forms.scss (مكونات تستخدم التكوين)
  • _index.scss الذي يعيد توجيه كل شيء مع بادئات مناسبة
  • إخفاء أي متغيرات داخلية/خاصة
  • أنشئ main.scss الذي يستخدم نظام التصميم الخاص بك مع تكوين مخصص