نظرة عامة على النواة المشتركة
يمثل @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. فإذا أُصلح خطأ ما، صُلح في الأطراف الأربعة معًا؛ وإذا أُضيف حد جديد، امتلكته الأطراف الأربعة معًا.
الـ 12 وحدة فرعية
Section titled “الـ 12 وحدة فرعية”| الوحدة | المسؤولية | التصديرات الجوهرية |
|---|---|---|
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 “فلسفة التصميم”دوال نقية، والحالة في طبقة واجهة المستخدم
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