تخطَّ إلى المحتوى

نظرة عامة على النواة المشتركة

يمثل @lh-ui/share/core/shared طبقة الخوارزميات العامة لأسرة lh-ui بأكملها—12 وحدة TypeScript بلا تبعيات، تجمع المنطق الذي تستخدمه المكوّنات جميعها، ولكن يسهل أن يكتبه كل طرف نسخة منه (بفروق دقيقة) فيُصبح تنفيذًا واحدًا:

تحديد موضع الطبقة المنبثقة، والتمرير الافتراضي، والتنقل بلوحة المفاتيح، وحلقة التركيز، وبناء سمات aria، وبدائيات التاريخ، وتطهير القيم العددية، وتمرير الأنماط… هذه الخوارزميات لا تنتمي إلى أي إطار: مدخلاتها بيانات عادية، ومخرجاتها بيانات عادية، ولا تلمس التفاعلية ولا الحالة العامة لـ DOM (وقلة من الدوال تقرأ DOM لكن مع حراس SSR).

إن المكوّن نفسه في الأطراف الأربعة lh-ui-plus وlh-ui-vue2 وlh-ui-react وlh-ui-uniapp يستخدم النسخة نفسها من computePosition والنسخة نفسها من getNextListIndex. فإذا أُصلح خطأ ما، صُلح في الأطراف الأربعة معًا؛ وإذا أُضيف حد جديد، امتلكته الأطراف الأربعة معًا.

الوحدة المسؤولية التصديرات الجوهرية
sx خاصية sx → أنماط مضمَّنة، بأولوية ثابتة «الجانب الواحد > مجموعة المحور > الاختصار» sxToStyle / mergeSx / LhSxProps
popper محرك تحديد موضع الطبقة المنبثقة: 12 موضعًا، وقلب المحور الرئيسي، واحتجاز المحور المتقاطع، وإزاحة السهم computePosition / parsePlacement / LhPlacement
virtual مجال التمرير الافتراضي بارتفاع ثابت (يشترك virtual-list وtable في الخوارزمية نفسها) computeRange / computeWindow / LH_VIRTUAL_OVERSCAN
keyboard تفاعل لوحة المفاتيح: الحكم على المفاتيح، وتنقل القوائم / الشبكات / range، وtype-ahead getNextListIndex / getNextGridCell / LH_KEYS
focus-trap إدارة التركيز: عدّ العناصر القابلة للتركيز، وحلقة Tab للتركيز، وسجل ملكية inert trapTabKey / setInertOutside / focusFirst
a11y المنشئات الذرية لسمات aria (بتوحيد دلالة «القيم الكاذبة تُحذف») getPopupTriggerAria / ariaExpanded / getDecorativeAria
date بدائيات التاريخ: أيام الشهر، والمقارنة، وحكم التعطيل، والتنسيق برموز ثابتة العرض formatDate / parseDate / isDateDisabled
format إقحام قوالب النص (العنصر النائب {key}) formatMessage
delay تطبيع تأخير الإظهار والإخفاء (تشترك فيه tooltip / popover / popconfirm) resolveDelay
pt دمج خصائص PT الممررة مباشر (دمج سطحي لـ class / style / attrs) mergePt / LhPtAttrs
sanitize تطهير القيم العددية: اعتراض NaN / Infinity عند المدخل sanitizeNumber / clamp / safePrecision
types الأنواع المشتركة المتحدة: الحجم / اللغة / النوع / الموضع LhComponentSize / LhComponentType

يُعيد مدخل التجميع @lh-ui/share/core/shared تصدير الوحدات الـ 12 جميعها عبر export *؛ ويمكن كذلك الاستيراد الدقيق حسب الوحدة من @lh-ui/share/core/shared/popper حتى لا يحمل الحزم سوى ما يُستعمل منه فعلًا.

دوال نقية، والحالة في طبقة واجهة المستخدم

Section titled “دوال نقية، والحالة في طبقة واجهة المستخدم”

دوال طبقة core لا تحتفظ بحالة المكوّن. وخذ popper مثلًا: يستقبل computePosition(trigger, popper, viewport, options) ثلاثة قيم rect حرفية ويُعيد { top, left, placement, arrowOffset }—فأمر «أين المُطلِق الآن، وما حجم الطبقة المنبثقة، وما حجم إطار العرض» كله تقيسه طبقة واجهة المستخدم في لحظة الاستدعاء وتمرره. ويعني هذا أن:

  • الدالة نفسها تصلح أن تعمل في watchEffect في Vue3، وفي useLayoutEffect في React، وفي onPageScroll في uniapp.
  • لا يحتاج اختبار الوحدة إلى عرض المكوّن: فكثير من حالات tests/unit/ هي «صنع مجموعة rect، والتأكد من المخرجات»، وتتشارك الأطراف الأربعة نتائج الاختبار نفسها (الخط الأحمر 3: اختبارات core الوحيدة موجودة في هذا المستودع).

حراس SSR هو العقد الافتراضي

Section titled “حراس SSR هو العقد الافتراضي”

قلة من الدوال تضطر إلى قراءة DOM (getWindowViewport، وgetFocusableElements، وsaveActiveElement). وجميعها يحكم في مدخله على typeof document === 'undefined' / typeof window === 'undefined' ويُعيد قيمة فارغة آمنة ([] / null / rect بأبعاد 0)، حتى لا تنهار عملية العرض في الخادم في Nuxt / Next / uniapp. وتُعلِّم صفحة كل دالة في الوثائق ما إذا كانت «آمنة في SSR» أو سلوك الحراسة الدقيق.

اصطلاح aria «القيم الكاذبة تُحذف»

Section titled “اصطلاح aria «القيم الكاذبة تُحذف»”

يتبع جميع منشئات وحدة a11y الاصطلاح نفسه: عندما تكون سمة aria المنطقية كاذبة يُخرَج undefined حتى لا يعرضها الإطار (فالتصريح الصريح بالنفي مثل aria-required: false هو ضجيج في معظم الأحيان). والاستثناء هو السمات التي تقتضي الذكر الصريح دلاليًا: aria-expanded: false وaria-invalid: false تُخرجان كما هما. ولمزيد من التفصيل راجع وثائق a11y.

التطهير عند المدخل، بلا دفاع في المصب

Section titled “التطهير عند المدخل، بلا دفاع في المصب”

وجود sanitize يُغني بقية دوال core عن كتابة دفاع Number.isFinite في كل موضع. فالقيم العددية الوافدة من الخارج مثل رقم الصفحة، والتباعد، وstep، وprecision تمر أولًا عبر sanitizeNumber قبل دخولها الخوارزمية، فتُستبدل NaN / Infinity بقيمة افتراضية آمنة. وهذا اختيار «اعتراض واحد، نظافة عامة»: فإمّا أن يضمن المستدعي بنفسه قانونية القيم ويستخدم clamp مباشرةً، أو يصرِّح بثقته في التطهير عند المدخل.

التبعيات بين الوحدات خفيفة جدًا

Section titled “التبعيات بين الوحدات خفيفة جدًا”

ثلاث فقط:

  • keyboard ← sanitize.clamp (احتجاز حدود التنقل)
  • popper ← sanitize.clamp + sanitize.sanitizeNumber (الاحتجاز وتطهير المدخلات)
  • shared/types ← constants.LH_SIZE_CONST / LH_LANGUAGE_CONST / LH_TYPES_CONST (import type، والأنواع المتحدة مُشتقة من الثوابت)

لا تبعيات دائرية، ولا اعتماد عكسي على locales أو طبقة واجهة المستخدم. ووحدة format هي ثمرة هذا الخط: فالإقحامات مثل '{n} نجمة' في rate و'إجمالي {total} عنصر' في pagination كانت تتطلب في الأصل العودة إلى singleton الخاص بـ locales، وبعد إنزالها إلى دالة نصية نقية لم تعد مكوّنات core تعتمد على التأثيرات الجانبية على مستوى الوحدة في locales.

@lh-ui/share/core/sanitize → clamp( )
返回值
(填好参数后点运行)

في أسفل كل صفحة من صفحات الوحدات الفرعية توجد كتلة تجريب كهذه: املأ المعاملات، وشغّلها في العميل مباشرةً، وانظر المخرجات.

Copyright © 2024-2026 FengMo WenXue