UNPKG

ivue-material-plus

Version:

A high quality UI components Library with Vue.js

334 lines (301 loc) • 7.33 kB
import { h } from 'vue'; import { hasOwn } from '@vue/shared'; import IvueCheckbox from '../ivue-checkbox/index.vue'; import IvueIcon from '../ivue-icon/index.vue'; import Loading from './loading.vue'; import { getProp } from '../../utils/objects'; // ts import type { VNode } from 'vue'; import type { TableColumnCtx } from './table-column/defaults'; import type { RenderRowData } from './table/defaults'; import type { Store } from './store'; const defaultClassNames = { selection: 'ivue-table-column--selection', expand: 'ivue-table--expand-column', }; // 行样式 export const cellStyles = { default: { order: '', }, selection: { width: 48, minWidth: 48, columnWidth: 48, order: '', }, expand: { width: 48, minWidth: 48, columnWidth: 48, order: '', }, index: { width: 48, minWidth: 48, columnWidth: 48, order: '', }, }; // 合并选项 export function mergeOptions<T, K>(defaults: T, config: K): T & K { const options = {} as T & K; let key; // 复制对象 for (key in defaults) { options[key] = defaults[key]; } // config for (key in config) { if (hasOwn(config as unknown as Record<string, any>, key)) { const value = config[key]; if (typeof value !== 'undefined') { options[key] = value; } } } return options; } // https://github.com/reduxjs/redux/blob/master/src/compose.js // 函数执行的顺序是从右到左 export function compose(...funcs) { if (funcs.length === 0) { return (arg) => arg; } if (funcs.length === 1) { return funcs[0]; } return funcs.reduce( (a, b) => (...args) => a(b(...args)) ); } // 渲染行 export function defaultRenderCell({ row, column, $index, }: { row: any; column: TableColumnCtx; $index: number; }) { // 字段名称 对应列内容的字段名 const property = column.property; const value = property && getProp(row, property).value; // 是否有格式化内容 if (column && column.formatter) { return column.formatter(row, column, value, $index); } // 普通渲染 return value?.toString?.() || ''; } // 列 export function treeCellPrefix( { row, treeNode, store }: RenderRowData, createPlaceholder = false ) { // 不是树节点 if (!treeNode) { // 创建占位符 if (createPlaceholder) { return [ h('span', { class: 'ivue-table-indent--placeholder', }), ]; } return null; } // ele const ele: VNode[] = []; const callback = (event) => { event.stopPropagation(); // 加载中 if (treeNode.loading) { return; } // 树形数据与懒加载 store.loadOrToggle(row); }; // 展示树形数据时,树节点的缩进 if (treeNode.indent) { ele.push( h('span', { class: 'ivue-table-indent', style: { 'padding-left': `${treeNode.indent}px`, }, }) ); } // 展开行 if (typeof treeNode.expanded === 'boolean' && !treeNode.noLazyChildren) { const expandClasses = [ 'ivue-table--expand-icon', { ['ivue-table--expand-icon__expandend']: treeNode.expanded, }, ]; let icon = 'chevron_right'; // 加载中 if (treeNode.loading) { icon = ''; } // 解析指令 ele.push( h( 'div', { class: expandClasses, onClick: callback, }, { default: () => { return [ icon ? h(IvueIcon, null, { default: () => icon, }) : h(Loading), ]; }, } ) ); } // 其他 else { ele.push( h('span', { class: 'ivue-table-indent--placeholder', }) ); } return ele; } // 需要替换的渲染函数 export const cellForced = { // 多选 selection: { // 渲染头部 renderHeader({ store }: { store: Store }) { return h(IvueCheckbox, { // 没有数据禁用 disabled: store.states.data.value && store.states.data.value.length === 0, // 是否选择了全部 modelValue: store.states.isAllSelected.value, // 更新modelValue 'onUpdate:modelValue': store.toggleAllSelection, // 中间状态 indeterminate: store.states.selection.value.length > 0 && !store.states.isAllSelected.value, // onClick onClick: (event: Event) => { event.stopPropagation(); }, }); }, // 渲染单元格 renderCell({ row, column, store, $index, }: { row: any; column: TableColumnCtx; store: Store; $index: string; }) { return h(IvueCheckbox, { disabled: column.selectable ? !column.selectable.call(null, row, $index) : false, modelValue: store.isSelected(row), onChange: () => { store.commit('rowSelectedChanged', row); }, // 阻止捕获和冒泡阶段中当前事件 onClick: (event: Event) => event.stopPropagation(), }); }, // 对应列是否可以排序 sortable: false, // 对应列是否可以通过拖动改变宽度 resizable: false, }, // 索引 index: { // 渲染头部 renderHeader({ column }: { column: TableColumnCtx }) { return column.label || '#'; }, // 渲染单元格 renderCell({ column, $index }: { column: TableColumnCtx; $index: number }) { let i = $index + 1; const index = column.index; // number if (typeof index === 'number') { i = $index + index; } // function else if (typeof index === 'function') { i = index($index); } return h('div', {}, [i]); }, }, expand: { // 渲染头部 renderHeader({ column }: { column: TableColumnCtx }) { return column.label || ''; }, renderCell({ row, store, expanded, }: { row: TableColumnCtx; store: Store; expanded: boolean; }) { // 切换展开 const handleToggleRowExpansion = (event: Event) => { event.stopPropagation(); // 切换行展开 store.toggleRowExpansion(row); }; return h( 'div', { class: [ 'ivue-table--expand-icon', { ['ivue-table--expand-icon__expandend']: expanded, }, ], onClick: handleToggleRowExpansion, }, { default: () => { return [ h(IvueIcon, null, { default: () => 'chevron_right', }), ]; }, } ); }, sortable: false, resizable: false, }, }; // 获取默认的class export const getDefaultClassName = (type) => { return defaultClassNames[type] || ''; };