Skip to content
API 风格:

شجرة Tree ​

تتم في دوال نقية بالطبقة الأساسية core كلٌّ من تحويل البيانات المسطحة إلى شجرة وانتشار التحديد، ولا يتحمَّل المكوّن سوى العرض والتنقّل بلوحة المفاتيح.

الاستخدام الأساسي ​

الاستخدام الأساسي
الواجهات
Vue
React
العمليات
vue
<script setup>
import { ref } from 'vue'
const treeData = [
  { key: 'a', label: 'الواجهات', children: [
    { key: 'a-1', label: 'Vue' },
    { key: 'a-2', label: 'React' },
  ] },
  { key: 'b', label: 'الخوادم', children: [{ key: 'b-1', label: 'Node' }] },
  { key: 'c', label: 'العمليات', disabled: true },
]
</script>

<template>
  <!-- الاستخدام الأساسي -->
  <LhTree :data="treeData" :default-expanded-keys="['a']" />
</template>
vue
<script>
export default {
  data() {
    return {
      treeData: [
        { key: 'a', label: 'الواجهات', children: [
          { key: 'a-1', label: 'Vue' },
          { key: 'a-2', label: 'React' },
        ] },
        { key: 'b', label: 'الخوادم', children: [{ key: 'b-1', label: 'Node' }] },
        { key: 'c', label: 'العمليات', disabled: true },
      ],
    }
  },
}
</script>

<template>
  <!-- الاستخدام الأساسي -->
  <LhTree :data="treeData" :default-expanded-keys="['a']" />
</template>

قابل للتحديد (متسلسل) ​

يتسلسل تحديد العقدة الأصل إلى جميع أحفادها؛ وعند تحديد جميع الأبناء تُحدَّد الأصل تلقائيًا، ويعرض التحديد الجزئي الحالة الوسيطة (indeterminate).

تسلسل التحديد
الواجهات
Vue
React
الخوادم
Node
العمليات
vue
<script setup lang="ts">
const treeData = [
  { key: 'a', label: 'الواجهات', children: [
    { key: 'a-1', label: 'Vue' },
    { key: 'a-2', label: 'React' },
  ] },
  { key: 'b', label: 'الخوادم', children: [{ key: 'b-1', label: 'Node' }] },
  { key: 'c', label: 'العمليات', disabled: true },
]
</script>

<template>
  <!-- تسلسل التحديد -->
  <LhTree :data="treeData" show-checkbox :default-expanded-keys="['a', 'b']" />
</template>
vue
<script>
export default {
  data() {
    return {
      treeData: [
        { key: 'a', label: 'الواجهات', children: [
          { key: 'a-1', label: 'Vue' },
          { key: 'a-2', label: 'React' },
        ] },
        { key: 'b', label: 'الخوادم', children: [{ key: 'b-1', label: 'Node' }] },
        { key: 'c', label: 'العمليات', disabled: true },
      ],
    }
  },
}
</script>

<template>
  <!-- تسلسل التحديد -->
  <LhTree :data="treeData" show-checkbox :default-expanded-keys="['a', 'b']" />
</template>

التحميل الكسول ​

عند تفعيل lazy، يستدعي توسيع عقدة غير محمَّلة دالة الاستدعاء load (يُرسِل resolve العقد الفرعية ويوسِّعها، بينما يُلغي reject)؛ ويُظهر سهم التحميل حالة دوران أثناءه. ويجب التصريح صراحةً بـ isLeaf: false للعقد القابلة للتحميل (وإلّا فالعقد التي بلا children تُعدّ ورقية ولا يظهر لها سهم التوسيع)؛ وإذا كانت العقد الفرعية المحمَّلة فروعًا بانتظار التحميل فلتُصرَّح هي الأخرى بـ isLeaf: false، أما الأوراق الحقيقية فتُصرَّح بـ isLeaf: true.

التحميل الكسول
vue
<script setup>
import { ref } from 'vue'

const lazyData = ref([
  { key: 'lazy', label: 'انقر للتحميل', isLeaf: false },
])

function loadNodes(node, resolve, reject) {
  // محاكاة طلب غير متزامن
  setTimeout(() => {
    if (node.key === 'lazy') {
      resolve([
        { key: 'lazy-1', label: 'عقدة فرعية أولى', isLeaf: true },
        { key: 'lazy-2', label: 'عقدة فرعية ثانية', isLeaf: true },
      ])
    } else {
      reject(new Error('nothing to load'))
    }
  }, 600)
}
</script>

<template>
  <!-- تحميل كسول -->
  <LhTree :data="lazyData" lazy :load="loadNodes" />
</template>
vue
<script>
export default {
  data() {
    return {
      lazyData: [{ key: 'lazy', label: 'انقر للتحميل', isLeaf: false }],
    }
  },
  methods: {
    // محاكاة طلب غير متزامن
    loadNodes(node, resolve, reject) {
      setTimeout(() => {
        if (node.key === 'lazy') {
          resolve([
            { key: 'lazy-1', label: 'عقدة فرعية أولى', isLeaf: true },
            { key: 'lazy-2', label: 'عقدة فرعية ثانية', isLeaf: true },
          ])
        } else {
          reject(new Error('nothing to load'))
        }
      }, 600)
    },
  },
}
</script>

<template>
  <!-- تحميل كسول -->
  <LhTree :data="lazyData" lazy :load="loadNodes" />
</template>

عدم ربط الأصل بالابن (checkStrictly) ​

عند تفعيل checkStrictly يعمل التحديد على العقدة نفسها فقط: بلا تسلسل للأحفاد، وبلا ارجاع للأصول، وبلا حالة وسيطة.

checkStrictly
الواجهات
Vue
React
الخوادم
Node
العمليات
vue
<script setup lang="ts">
const treeData = [
  { key: 'a', label: 'الواجهات', children: [
    { key: 'a-1', label: 'Vue' },
    { key: 'a-2', label: 'React' },
  ] },
  { key: 'b', label: 'الخوادم', children: [{ key: 'b-1', label: 'Node' }] },
  { key: 'c', label: 'العمليات', disabled: true },
]
</script>

<template>
  <!-- عدم ربط الأصل بالابن -->
  <LhTree :data="treeData" show-checkbox check-strictly :default-expanded-keys="['a', 'b']" />
</template>
vue
<script>
export default {
  data() {
    return {
      treeData: [
        { key: 'a', label: 'الواجهات', children: [
          { key: 'a-1', label: 'Vue' },
          { key: 'a-2', label: 'React' },
        ] },
        { key: 'b', label: 'الخوادم', children: [{ key: 'b-1', label: 'Node' }] },
        { key: 'c', label: 'العمليات', disabled: true },
      ],
    }
  },
}
</script>

<template>
  <!-- عدم ربط الأصل بالابن -->
  <LhTree :data="treeData" show-checkbox check-strictly :default-expanded-keys="['a', 'b']" />
</template>

التحديد والمفاتيح المتحكَّم بها ​

يسمح multiple بالتحديد المتعدد؛ ويُوسِّع expand-on-click-node العقدة أو يطويها عند النقر عليها؛ وتتحكَّم default-selected-keys / v-model:selected-keys في التحديد؛ وdefault-checked-keys / v-model:checked-keys في التحديد بخانات الاختيار؛ وdefault-expanded-keys / v-model:expanded-keys في التوسيع؛ ويعطّل disabled الشجرة بأكملها.

تحديد وتحديد بخانات متحكَّم بهما
التصميم
الألوان
الخطوط
الهندسة

محدَّد: [ "x" ] | محدَّد بخانة: [ "x-1" ]

تعطيل الشجرة بأكملها
الهندسة
vue
<script setup>
import { ref } from 'vue'
const selKeys = ref(['x'])
const chkKeys = ref(['x-1'])
const ctrlData = [
  { key: 'x', label: 'التصميم', children: [
    { key: 'x-1', label: 'الألوان' },
    { key: 'x-2', label: 'الخطوط' },
  ] },
  { key: 'y', label: 'الهندسة' },
]
</script>

<template>
  <!-- تحديد وتحديد بخانات متحكَّم بهما -->
  <LhTree
    v-model:selected-keys="selKeys"
    v-model:checked-keys="chkKeys"
    :data="ctrlData"
    multiple
    expand-on-click-node
    :default-expanded-keys="['x']"
    :default-selected-keys="['x']"
    :default-checked-keys="['x-1']"
  />
  <p class="demo-tree-log">محدَّد: {{ selKeys }} | محدَّد بخانة: {{ chkKeys }}</p>
  <!-- تعطيل الشجرة بأكملها -->
  <LhTree :data="ctrlData" disabled />
</template>
vue
<script>
export default {
  data() {
    return {
      selKeys: ['x'],
      chkKeys: ['x-1'],
      ctrlData: [
        { key: 'x', label: 'التصميم', children: [
          { key: 'x-1', label: 'الألوان' },
          { key: 'x-2', label: 'الخطوط' },
        ] },
        { key: 'y', label: 'الهندسة' },
      ],
    }
  },
}
</script>

<template>
  <!-- تحديد وتحديد بخانات متحكَّم بهما -->
  <LhTree
    v-model:selected-keys="selKeys"
    v-model:checked-keys="chkKeys"
    :data="ctrlData"
    multiple
    expand-on-click-node
    :default-expanded-keys="['x']"
    :default-selected-keys="['x']"
    :default-checked-keys="['x-1']"
  />
  <p class="demo-tree-log">محدَّد: {{ selKeys }} | محدَّد بخانة: {{ chkKeys }}</p>
  <!-- تعطيل الشجرة بأكملها -->
  <LhTree :data="ctrlData" disabled />
</template>

API ​

LhTree Props ​

اسم الخاصيةالوصفالنوعالقيمة الافتراضية
dataبيانات الشجرة[LhTreeNode](#type-LhTreeNode)[]—
showCheckboxإظهار خانات الاختيارbooleanfalse
multipleتحديد متعدد (النقر على عقدة يبدِّل تحديدها بدلًا من استبداله)booleanfalse
expandOnClickNodeتوسيع/طي العقدة غير الورقية عند النقر عليهاbooleantrue
defaultExpandedKeysمفاتيح التوسيع الافتراضية (غير متحكَّم بها)string[]() => []
expandedKeysمفاتيح التوسيع المتحكَّم بهاstring[]—
defaultSelectedKeysمفاتيح التحديد الافتراضية (غير متحكَّم بها)string[]() => []
selectedKeysمفاتيح التحديد المتحكَّم بهاstring[]—
defaultCheckedKeysمفاتيح تحديد الخانات الافتراضية (غير متحكَّم بها)string[]() => []
checkedKeysمفاتيح تحديد الخانات المتحكَّم بهاstring[]—
checkStrictlyعدم ربط تحديد الأصل بالابن (التحديد يعمل على العقدة نفسها فقط، بلا تسلسل وحالة وسيطة)booleanfalse
lazyوضع التحميل الكسول (يستدعي load عند توسيع عقدة غير محمَّلة)booleanfalse
loadدالة الاستدعاء للتحميل الكسول (يُرسِل resolve العقد الفرعية ويوسِّعها، ويُلغي reject)(node: LhTreeNode, resolve: (children: LhTreeNode[]) => void, reject: (reason?: unknown) => void) => void—
disabledالتعطيل الكليbooleanfalse
sxخصائص التخطيط السريع sxLhSxProps—

Events ​

اسم الحدثالوصفوسائط الاستدعاء
update:expandedKeysيُطلَق عند تغيُّر قائمة مفاتيح التوسيع، ويُستخدم مع v-model:expanded-keys(keys: string[])
update:selectedKeysيُطلَق عند تغيُّر قائمة مفاتيح التحديد، ويُستخدم مع v-model:selected-keys(keys: string[])
update:checkedKeysيُطلَق عند تغيُّر قائمة مفاتيح تحديد الخانات، ويُستخدم مع v-model:checked-keys(keys: string[])
selectيُطلَق بعد تحديد عقدة بالنقر / تبديل تحديدها(key: string, node: LhTreeNode)
checkيُطلَق بعد تغيُّر التحديد بخانة(keys: string[], node: LhTreeNode)
expandيُطلَق بعد توسيع / طي عقدة(key: string, expanded: boolean)
nodeLoadيُطلَق بعد عودة العقد الفرعية للتحميل الكسول(node: LhTreeNode, children: LhTreeNode[])

الفتحات: node (نطاقها { node, level, expanded, selected })، وempty.

LhTreeNode ​

الحقلالوصفالنوع
keyمفتاح فريدstring
labelالنص الظاهرstring
childrenالعقد الفرعيةLhTreeNode[]
disabledالتعطيلboolean
isLeafهل هي ورقة (عند عدم التمرير يُستدلَّ عليها من children)boolean

إتاحة الوصول ​

  • role="tree" + role="treeitem"، مع إتاحة aria-level / aria-expanded / aria-selected / aria-disabled بالكامل
  • خانة الاختيار role="checkbox" + aria-checked (الحالة الوسيطة هي mixed)
  • لوحة المفاتيح (وفق نمط APG tree): ↑/↓ للتنقّل بين العناصر (مع تخطّي المعطَّلة والتدوير)، → للتوسيع أو الدخول إلى أول ابن، ← للطي أو العودة إلى الأصل، وHome/End لأول وآخر عنصر، وEnter/Space للتنشيط؛ roving tabindex

تعريفات الأنواع ​

بنية الأنواع التي يُصدِّرها هذا المكوّن بلغة TypeScript كالتالي (مستخرجة آليًا من packages/components/tree/src/types.ts و@lh-ui/share/core/*؛ انقر كل عنصر لعرض التعريف الكامل؛ لأوصاف الخصائص انظر جدول Props أعلاه):

LhTreeProps
ts
export interface LhTreeProps {
  /** بيانات الشجرة */
  data: LhTreeNode[]
  /** إظهار خانات الاختيار */
  showCheckbox?: boolean
  /** تحديد متعدد (النقر على عقدة يبدِّل تحديدها بدلًا من استبداله) */
  multiple?: boolean
  /** توسيع/طي العقدة غير الورقية عند النقر عليها */
  expandOnClickNode?: boolean
  /** مفاتيح التوسيع الافتراضية (غير متحكَّم بها) */
  defaultExpandedKeys?: string[]
  /** مفاتيح التوسيع المتحكَّم بها */
  expandedKeys?: string[]
  /** مفاتيح التحديد الافتراضية (غير متحكَّم بها) */
  defaultSelectedKeys?: string[]
  /** مفاتيح التحديد المتحكَّم بها */
  selectedKeys?: string[]
  /** مفاتيح تحديد الخانات الافتراضية (غير متحكَّم بها) */
  defaultCheckedKeys?: string[]
  /** مفاتيح تحديد الخانات المتحكَّم بها */
  checkedKeys?: string[]
  /** عدم ربط تحديد الأصل بالابن (التحديد يعمل على العقدة نفسها فقط، بلا تسلسل وحالة وسيطة) */
  checkStrictly?: boolean
  /** وضع التحميل الكسول: يستدعي load عند توسيع عقدة غير ورقية غير محمَّلة */
  lazy?: boolean
  /** دالة الاستدعاء للتحميل الكسول: يُرسِل resolve العقد الفرعية ويوسِّعها، ويُلغي reject (أو رفع خطأ) */
  load?: (
    node: LhTreeNode,
    resolve: (children: LhTreeNode[]) => void,
    reject: (reason?: unknown) => void,
  ) => void
  /** تعطيل كلي */
  disabled?: boolean
  /** خصائص التخطيط السريع sx */
  sx?: LhSxProps
}
LhFlatTreeNode (من @lh-ui/share/core/tree)
ts
/** عقدة مسطَّحة (لأغراض العرض) */
export interface LhFlatTreeNode {
  node: LhTreeNode
  key: string
  level: number
  parentKey: string | null
  /** سلسلة الأصول (لا تشمل العقدة نفسها) */
  ancestorKeys: string[]
  /** هل هي ورقة */
  isLeaf: boolean
}
LhTreeNode (من @lh-ui/share/core/tree)
ts
/** بيانات عقدة الشجرة */
export interface LhTreeNode {
  /** مفتاح فريد */
  key: string
  /** النص الظاهر */
  label: string
  /** العقد الفرعية */
  children?: LhTreeNode[]
  /** تعطيل */
  disabled?: boolean
  /** هل هي ورقة (عند عدم التمرير يُستدلَّ عليها من children) */
  isLeaf?: boolean
}
LhTreeCheckState (من @lh-ui/share/core/tree)
ts
/** حالة التحديد */
export type LhTreeCheckState = 'checked' | 'indeterminate' | 'unchecked'

جمال التقاليد، أساس الكود