diff --git a/examples/sites/demos/mobile-first/app/space/space-order.vue b/examples/sites/demos/mobile-first/app/space/space-order.vue
index d017976b15..b375692405 100644
--- a/examples/sites/demos/mobile-first/app/space/space-order.vue
+++ b/examples/sites/demos/mobile-first/app/space/space-order.vue
@@ -1,13 +1,14 @@
- First Button
- Second Button
- Third Button
+ First Button
+ Second Button
+ Third Button
+ Fourth Button
diff --git a/examples/sites/demos/mobile-first/app/space/webdoc/space.js b/examples/sites/demos/mobile-first/app/space/webdoc/space.js
index 54fe193819..74e7009a04 100644
--- a/examples/sites/demos/mobile-first/app/space/webdoc/space.js
+++ b/examples/sites/demos/mobile-first/app/space/webdoc/space.js
@@ -9,8 +9,8 @@ export default {
'en-US': 'Basic Usage'
},
desc: {
- 'zh-CN': '
默认横向排列,支持自动插槽分隔间距
',
- 'en-US': 'Horizontal layout by default, with automatic spacing between slots
'
+ 'zh-CN': '默认采用横向布局(row),自动为插槽内容添加间距。
',
+ 'en-US': 'Uses horizontal layout (row) by default, automatically adding spacing between slot content.
'
},
codeFiles: ['basic-usage.vue']
},
@@ -21,9 +21,10 @@ export default {
'en-US': 'Spacing Size'
},
desc: {
- 'zh-CN': '通过 `size` 属性设置间距,支持 small / medium / large 或自定义数值 / 数组。
',
+ 'zh-CN':
+ '通过 size
属性设置间距大小,支持 small、medium、large 预定义值或自定义数值/数组。
',
'en-US':
- 'Use the `size` prop to define spacing. Supports small / medium / large or custom values / arrays.
'
+ 'Use the size
prop to set spacing size. Supports predefined values (small, medium, large) or custom values/arrays.
'
},
codeFiles: ['space-size.vue']
},
@@ -31,11 +32,12 @@ export default {
demoId: 'space-direction',
name: {
'zh-CN': '排列方向',
- 'en-US': 'Direction'
+ 'en-US': 'Layout Direction'
},
desc: {
- 'zh-CN': '通过 `direction` 属性设置排列方向,支持 horizontal 或 vertical。
',
- 'en-US': 'Use the `direction` prop to control layout direction: horizontal or vertical.
'
+ 'zh-CN': '通过 direction
属性设置布局方向,支持 row(横向)或 column(纵向)。
',
+ 'en-US':
+ 'Use the direction
prop to set layout direction: row (horizontal) or column (vertical).
'
},
codeFiles: ['space-direction.vue']
},
@@ -43,37 +45,38 @@ export default {
demoId: 'space-wrap',
name: {
'zh-CN': '换行显示',
- 'en-US': 'Wrapping'
+ 'en-US': 'Content Wrapping'
},
desc: {
- 'zh-CN': '通过 `wrap` 属性控制是否换行显示内容。
',
- 'en-US': 'Use the `wrap` prop to enable wrapping of child items.
'
+ 'zh-CN': '通过 wrap
属性控制子项内容是否换行显示。
',
+ 'en-US': 'Use the wrap
prop to control whether child items wrap to multiple lines.
'
},
codeFiles: ['space-wrap.vue']
},
{
demoId: 'space-align',
name: {
- 'zh-CN': '对齐方式',
- 'en-US': 'Alignment'
+ 'zh-CN': '交叉轴对齐',
+ 'en-US': 'Cross Axis Alignment'
},
desc: {
- 'zh-CN': '通过 `align` 设置交叉轴对齐方式,如 start、center、end、baseline 等。
',
- 'en-US': 'Use `align` to define alignment on the cross axis, such as start, center, end, or baseline.
'
+ 'zh-CN': '通过 align
属性设置交叉轴对齐方式,支持 start、center、end、baseline 等值。
',
+ 'en-US':
+ 'Use the align
prop to define alignment on the cross axis, supporting values like start, center, end, and baseline.
'
},
codeFiles: ['space-align.vue']
},
{
demoId: 'space-justify',
name: {
- 'zh-CN': '主轴对齐方式',
- 'en-US': 'Justify Content'
+ 'zh-CN': '主轴对齐',
+ 'en-US': 'Main Axis Justification'
},
desc: {
'zh-CN':
- '通过 `justify` 设置主轴对齐方式,如 start、center、end、space-between、space-around、space-evenly。
',
+ '通过 justify
属性设置主轴对齐方式,支持 start、center、end、space-between、space-around、space-evenly。
',
'en-US':
- 'Use `justify` to set main axis alignment like start, center, end, space-between, space-around, space-evenly.
'
+ 'Use the justify
prop to set main axis alignment, supporting start, center, end, space-between, space-around, and space-evenly.
'
},
codeFiles: ['space-justify.vue']
},
@@ -81,11 +84,13 @@ export default {
demoId: 'space-order',
name: {
'zh-CN': '自定义排序',
- 'en-US': 'Custom Order'
+ 'en-US': 'Custom Ordering'
},
desc: {
- 'zh-CN': '通过 `order` 属性传入 key 数组,自定义子元素渲染顺序。
',
- 'en-US': 'Use the `order` prop with a key array to customize rendering order of children.
'
+ 'zh-CN':
+ '通过 order
属性传入 key 数组来自定义子元素的渲染顺序,未设置 key 的子元素将自动排列在最后。
',
+ 'en-US':
+ 'Use the order
prop with an array of keys to customize the rendering order of child elements. Children without defined keys are automatically arranged at the end.
'
},
codeFiles: ['space-order.vue']
}
diff --git a/examples/sites/demos/pc/app/space/space-order.vue b/examples/sites/demos/pc/app/space/space-order.vue
index d017976b15..b375692405 100644
--- a/examples/sites/demos/pc/app/space/space-order.vue
+++ b/examples/sites/demos/pc/app/space/space-order.vue
@@ -1,13 +1,14 @@
- First Button
- Second Button
- Third Button
+ First Button
+ Second Button
+ Third Button
+ Fourth Button
diff --git a/examples/sites/demos/pc/app/space/webdoc/space.js b/examples/sites/demos/pc/app/space/webdoc/space.js
index 62fd1cb219..74e7009a04 100644
--- a/examples/sites/demos/pc/app/space/webdoc/space.js
+++ b/examples/sites/demos/pc/app/space/webdoc/space.js
@@ -3,14 +3,14 @@ export default {
owner: '',
demos: [
{
- demoId: 'basic-usage',
+ demoId: 'basic-space',
name: {
'zh-CN': '基本用法',
'en-US': 'Basic Usage'
},
desc: {
- 'zh-CN': '默认横向排列,支持自动插槽分隔间距
',
- 'en-US': 'Horizontal layout by default, with automatic spacing between slots
'
+ 'zh-CN': '默认采用横向布局(row),自动为插槽内容添加间距。
',
+ 'en-US': 'Uses horizontal layout (row) by default, automatically adding spacing between slot content.
'
},
codeFiles: ['basic-usage.vue']
},
@@ -21,9 +21,10 @@ export default {
'en-US': 'Spacing Size'
},
desc: {
- 'zh-CN': '通过 `size` 属性设置间距,支持 small / medium / large 或自定义数值 / 数组。
',
+ 'zh-CN':
+ '通过 size
属性设置间距大小,支持 small、medium、large 预定义值或自定义数值/数组。
',
'en-US':
- 'Use the `size` prop to define spacing. Supports small / medium / large or custom values / arrays.
'
+ 'Use the size
prop to set spacing size. Supports predefined values (small, medium, large) or custom values/arrays.
'
},
codeFiles: ['space-size.vue']
},
@@ -31,11 +32,12 @@ export default {
demoId: 'space-direction',
name: {
'zh-CN': '排列方向',
- 'en-US': 'Direction'
+ 'en-US': 'Layout Direction'
},
desc: {
- 'zh-CN': '通过 `direction` 属性设置排列方向,支持 row 或column。
',
- 'en-US': 'Use the `direction` prop to control layout direction: row or column.
'
+ 'zh-CN': '通过 direction
属性设置布局方向,支持 row(横向)或 column(纵向)。
',
+ 'en-US':
+ 'Use the direction
prop to set layout direction: row (horizontal) or column (vertical).
'
},
codeFiles: ['space-direction.vue']
},
@@ -43,37 +45,38 @@ export default {
demoId: 'space-wrap',
name: {
'zh-CN': '换行显示',
- 'en-US': 'Wrapping'
+ 'en-US': 'Content Wrapping'
},
desc: {
- 'zh-CN': '通过 `wrap` 属性控制是否换行显示内容。
',
- 'en-US': 'Use the `wrap` prop to enable wrapping of child items.
'
+ 'zh-CN': '通过 wrap
属性控制子项内容是否换行显示。
',
+ 'en-US': 'Use the wrap
prop to control whether child items wrap to multiple lines.
'
},
codeFiles: ['space-wrap.vue']
},
{
demoId: 'space-align',
name: {
- 'zh-CN': '对齐方式',
- 'en-US': 'Alignment'
+ 'zh-CN': '交叉轴对齐',
+ 'en-US': 'Cross Axis Alignment'
},
desc: {
- 'zh-CN': '通过 `align` 设置交叉轴对齐方式,如 start、center、end、baseline 等。
',
- 'en-US': 'Use `align` to define alignment on the cross axis, such as start, center, end, or baseline.
'
+ 'zh-CN': '通过 align
属性设置交叉轴对齐方式,支持 start、center、end、baseline 等值。
',
+ 'en-US':
+ 'Use the align
prop to define alignment on the cross axis, supporting values like start, center, end, and baseline.
'
},
codeFiles: ['space-align.vue']
},
{
demoId: 'space-justify',
name: {
- 'zh-CN': '主轴对齐方式',
- 'en-US': 'Justify Content'
+ 'zh-CN': '主轴对齐',
+ 'en-US': 'Main Axis Justification'
},
desc: {
'zh-CN':
- '通过 `justify` 设置主轴对齐方式,如 start、center、end、space-between、space-around、space-evenly。
',
+ '通过 justify
属性设置主轴对齐方式,支持 start、center、end、space-between、space-around、space-evenly。
',
'en-US':
- 'Use `justify` to set main axis alignment like start, center, end, space-between, space-around, space-evenly.
'
+ 'Use the justify
prop to set main axis alignment, supporting start, center, end, space-between, space-around, and space-evenly.
'
},
codeFiles: ['space-justify.vue']
},
@@ -81,11 +84,13 @@ export default {
demoId: 'space-order',
name: {
'zh-CN': '自定义排序',
- 'en-US': 'Custom Order'
+ 'en-US': 'Custom Ordering'
},
desc: {
- 'zh-CN': '通过 `order` 属性传入 key 数组,自定义子元素渲染顺序。
',
- 'en-US': 'Use the `order` prop with a key array to customize rendering order of children.
'
+ 'zh-CN':
+ '通过 order
属性传入 key 数组来自定义子元素的渲染顺序,未设置 key 的子元素将自动排列在最后。
',
+ 'en-US':
+ 'Use the order
prop with an array of keys to customize the rendering order of child elements. Children without defined keys are automatically arranged at the end.
'
},
codeFiles: ['space-order.vue']
}
diff --git a/packages/renderless/src/space/vue.ts b/packages/renderless/src/space/vue.ts
index 8396e0d468..a385d92fee 100644
--- a/packages/renderless/src/space/vue.ts
+++ b/packages/renderless/src/space/vue.ts
@@ -2,14 +2,47 @@
import type { ISpaceProps } from '@/types'
import { getGapStyle } from './index'
-export const api = ['state']
+export const api = ['state', 'orderedChildren']
-export const renderless = (props: ISpaceProps, hooks, { constants }) => {
+function isVNodeFn(node: any): boolean {
+ return !!(node && (node.__v_isVNode || node.componentOptions))
+}
+
+export const renderless = (props: ISpaceProps, hooks, { slots }) => {
const { reactive, computed } = hooks
const state = reactive({
gapStyle: computed(() => getGapStyle(props))
})
- return { state }
+ // 排序逻辑
+ const orderedChildren = computed(() => {
+ const children = slots.default?.() || []
+
+ // 过滤掉非 VNode 或注释节点
+ const validChildren = children.filter((v) => {
+ if (!isVNodeFn(v)) return false
+ const type = (v as any).type
+ return type !== 'Comment' && type !== Symbol.for('v-comment')
+ })
+
+ if (!props.order?.length) return validChildren
+
+ // 根据 key 或 class 建立索引
+ const map: Record = {}
+ validChildren.forEach((child) => {
+ const key = child.key ?? (Array.isArray(child.props?.class) ? child.props.class.join(' ') : child.props?.class)
+ if (key) map[String(key)] = child
+ })
+
+ // 按 order 排序
+ const sorted = props.order.map((k) => map[k]).filter(Boolean)
+
+ // 剩余没有在 order 里的保持原顺序
+ const rest = validChildren.filter((v) => !props.order.includes(String(v.key)))
+
+ return [...sorted, ...rest]
+ })
+
+ return { state, orderedChildren }
}
diff --git a/packages/vue/src/space/__tests__/space.test.tsx b/packages/vue/src/space/__tests__/space.test.tsx
index bf626618f1..ad7c90f132 100644
--- a/packages/vue/src/space/__tests__/space.test.tsx
+++ b/packages/vue/src/space/__tests__/space.test.tsx
@@ -5,27 +5,6 @@ import Space from '@opentiny/vue-space'
describe('PC Mode', () => {
const mount = mountPcMode
- test('base 基本用法', async () => {
- const wrapper = mount(() => (
-
- Item 1
- Item 2
-
- ))
-
- // 1. 验证容器元素
- expect(wrapper.find('[data-tag="tiny-space"]').exists()).toBe(true)
-
- // 2. 验证子元素
- expect(wrapper.findAll('[data-tag="tiny-space"] > *').length).toBe(2)
-
- // 3. 验证文本内容
- expect(wrapper.text()).toContain('Item 1')
- expect(wrapper.text()).toContain('Item 2')
-
- wrapper.unmount()
- })
-
test('props direction', async () => {
const wrapper = mount(() => (
@@ -73,4 +52,20 @@ describe('PC Mode', () => {
expect(wrapper.text()).toContain('Slot 2')
wrapper.unmount()
})
+
+ test('child element order', async () => {
+ const wrapper = mount(() => (
+
+ A
+ B
+ C
+
+ ))
+ const items = wrapper.findAll('.item')
+ expect(items.length).toBe(3)
+ expect(items[0].text()).toBe('A')
+ expect(items[1].text()).toBe('B')
+ expect(items[2].text()).toBe('C')
+ wrapper.unmount()
+ })
})
diff --git a/packages/vue/src/space/src/index.ts b/packages/vue/src/space/src/index.ts
index fee74dd7c8..2bcbd910ba 100644
--- a/packages/vue/src/space/src/index.ts
+++ b/packages/vue/src/space/src/index.ts
@@ -39,6 +39,10 @@ export const spaceProps = {
type: String,
default: ''
},
+ order: {
+ type: Array as PropType,
+ default: () => []
+ },
/** 自定义样式 */
customStyle: {
type: Object as PropType>,
diff --git a/packages/vue/src/space/src/mobile-first.vue b/packages/vue/src/space/src/mobile-first.vue
index 5ba522b46c..921e70350f 100644
--- a/packages/vue/src/space/src/mobile-first.vue
+++ b/packages/vue/src/space/src/mobile-first.vue
@@ -1,31 +1,73 @@
-
+
+
+
diff --git a/packages/vue/src/space/src/pc.vue b/packages/vue/src/space/src/pc.vue
index 56be83af23..6abeac5262 100644
--- a/packages/vue/src/space/src/pc.vue
+++ b/packages/vue/src/space/src/pc.vue
@@ -1,25 +1,5 @@
-
-
-
-
-
-