element-plus
Version:
A Component Library for Vue3.0
214 lines (195 loc) • 6.15 kB
text/typescript
import { nextTick, getCurrentInstance, unref, Ref } from 'vue'
import { arrayFind } from '@element-plus/utils/util'
import useWatcher from './watcher'
import { TableColumnCtx } from '../table-column/defaults'
import { Filter, Sort, Table } from '../table/defaults'
interface WatcherPropsData<T> {
data: Ref<T[]>
rowKey: Ref<string>
}
function replaceColumn<T>(
array: TableColumnCtx<T>[],
column: TableColumnCtx<T>,
) {
return array.map(item => {
if (item.id === column.id) {
return column
} else if (item.children?.length) {
item.children = replaceColumn(item.children, column)
}
return item
})
}
function sortColumn<T>(array: TableColumnCtx<T>[]) {
array.forEach(item => {
item.no = item.getColumnIndex?.()
if (item.children?.length) {
sortColumn(item.children)
}
})
array.sort((cur, pre) => cur.no - pre.no)
}
function useStore<T>() {
const instance = getCurrentInstance() as Table<T>
const watcher = useWatcher<T>()
type StoreStates = typeof watcher.states
const mutations = {
setData(states: StoreStates, data: T[]) {
const dataInstanceChanged = unref(states.data) !== data
states.data.value = data
states._data.value = data
instance.store.execQuery()
// 数据变化,更新部分数据。
// 没有使用 computed,而是手动更新部分数据 https://github.com/vuejs/vue/issues/6660#issuecomment-331417140
instance.store.updateCurrentRowData()
instance.store.updateExpandRows()
if (unref(states.reserveSelection)) {
instance.store.assertRowKey()
instance.store.updateSelectionByRowKey()
} else {
if (dataInstanceChanged) {
instance.store.clearSelection()
} else {
instance.store.cleanSelection()
}
}
instance.store.updateAllSelected()
if (instance.$ready) {
instance.store.scheduleLayout()
}
},
insertColumn(
states: StoreStates,
column: TableColumnCtx<T>,
parent: TableColumnCtx<T>,
) {
const array = unref(states._columns)
let newColumns = []
if (!parent) {
array.push(column)
newColumns = array
} else {
if (parent && !parent.children) {
parent.children = []
}
parent.children.push(column)
newColumns = replaceColumn(array, parent)
}
sortColumn(newColumns)
states._columns.value = newColumns
if (column.type === 'selection') {
states.selectable.value = column.selectable
states.reserveSelection.value = column.reserveSelection
}
if (instance.$ready) {
instance.store.updateColumns() // hack for dynamics insert column
instance.store.scheduleLayout()
}
},
removeColumn(
states: StoreStates,
column: TableColumnCtx<T>,
parent: TableColumnCtx<T>,
) {
const array = unref(states._columns) || []
if (parent) {
parent.children.splice(
parent.children.findIndex(item => item.id === column.id),
1,
)
if (parent.children.length === 0) {
delete parent.children
}
states._columns.value = replaceColumn(array, parent)
} else {
const index = array.indexOf(column)
if (index > -1) {
array.splice(index, 1)
states._columns.value = array
}
}
if (instance.$ready) {
instance.store.updateColumns() // hack for dynamics remove column
instance.store.scheduleLayout()
}
},
sort(states: StoreStates, options: Sort) {
const { prop, order, init } = options
if (prop) {
const column = arrayFind(
unref(states.columns),
column => column.property === prop,
)
if (column) {
column.order = order
instance.store.updateSort(column, prop, order)
instance.store.commit('changeSortCondition', { init })
}
}
},
changeSortCondition(states: StoreStates, options: Sort) {
// 修复 pr https://github.com/ElemeFE/element/pull/15012 导致的 bug
const { sortingColumn: column, sortProp: prop, sortOrder: order } = states
if (unref(order) === null) {
states.sortingColumn.value = null
states.sortProp.value = null
}
const ingore = { filter: true }
instance.store.execQuery(ingore)
if (!options || !(options.silent || options.init)) {
instance.emit('sort-change', {
column: unref(column),
prop: unref(prop),
order: unref(order),
})
}
instance.store.updateTableScrollY()
},
filterChange(_states: StoreStates, options: Filter<T>) {
const { column, values, silent } = options
const newFilters = instance.store.updateFilters(column, values)
instance.store.execQuery()
if (!silent) {
instance.emit('filter-change', newFilters)
}
instance.store.updateTableScrollY()
},
toggleAllSelection() {
instance.store.toggleAllSelection()
},
rowSelectedChanged(_states, row: T) {
instance.store.toggleRowSelection(row)
instance.store.updateAllSelected()
},
setHoverRow(states: StoreStates, row: T) {
states.hoverRow.value = row
},
setCurrentRow(_states, row: T) {
instance.store.updateCurrentRow(row)
},
}
const commit = function(name: keyof typeof mutations, ...args) {
const mutations = instance.store.mutations
if (mutations[name]) {
mutations[name].apply(instance, [instance.store.states].concat(args))
} else {
throw new Error(`Action not found: ${name}`)
}
}
const updateTableScrollY = function() {
nextTick(() => instance.layout.updateScrollY.apply(instance.layout))
}
return {
...watcher,
mutations,
commit,
updateTableScrollY,
}
}
export default useStore
class HelperStore<T> {
Return = useStore<T>()
}
type StoreFilter = Record<string, string[]>
type Store<T> = HelperStore<T>['Return']
export type { WatcherPropsData, Store, StoreFilter }