sinter-compositions
Version:
vue3 composition 工具库
90 lines (78 loc) • 2.43 kB
text/typescript
import {ref} from 'vue'
const defaultProps = {
key: 'id',
children: 'children'
}
type EachParams = {
level: number
parentIndex: number
parent: any | null
}
type CallbackParams = EachParams & {
hasChildren: boolean
index: number
}
export function useTree({props = defaultProps} = {}, d: Array<any> = []) {
const data = ref([] as any[])
function each(callback: (node: any, params: CallbackParams) => void | any) {
const _each = (d: any [], {
level, parentIndex, parent
}: EachParams): void | any => {
for (let i = 0; i < d.length; i++) {
const node = d[i] as any
const hasChildren = node[props.children] && Array.isArray(node[props.children]) && node[props.children].length > 0
const res = callback(d[i], {level, parentIndex, hasChildren, parent, index: i})
if (typeof res === 'undefined' && hasChildren) {
return _each(node[props.children], {
level: level + 1, parentIndex: i, parent: node
})
}
return res
}
}
return _each(data.value, {
level: 1,
parentIndex: -1,
parent: null
})
}
function find(key: string): null | any {
let r = null
each((node: any) => {
if (node[props.key] === key) return r = node
})
return r
}
function set(d: any []) {
data.value = d
}
function remove(key: string) {
each((node: any, {level, parent, index}) => {
if (node[props.key] === key) {
if (level === 1) data.value.splice(data.value.find(i => i[props.key] === key), 1)
else {
parent[props.children].splice(index, 1)
}
return node
}
})
}
function append(key: string, node: any) {
const current = find(key)
if (current !== null) {
if (!current[props.children] || !Array.isArray(current[props.children])) {
current[props.children] = []
}
current.push(node)
}
}
const handlers = {
each,
find,
remove,
append,
set
}
const result: [typeof data, typeof handlers] = [data, handlers]
return result
}