UNPKG

ivue-material-plus

Version:

A high quality UI components Library with Vue.js

307 lines (247 loc) • 7.24 kB
import { Comment, computed, getCurrentInstance, ref, watchEffect, h, } from 'vue'; import { defaultRenderCell, treeCellPrefix, cellForced, getDefaultClassName, } from '../config'; import { parseWidth, parseMinWidth } from '../utils'; // type import type { TableColumn, TableColumnCtx, ColumnParent } from './defaults'; import type { Table, RenderRowData } from '../table/defaults'; import type { ComputedRef } from 'vue'; const prefixCls = 'ivue-table'; function useRender( props: TableColumnCtx, slots, parentDom: ComputedRef<Table> ) { const vm = getCurrentInstance() as TableColumn; // 列id const columnId = ref<string>(''); // 是否是嵌套的子列 const isSubColumn = ref<boolean>(false); // 对齐方向 const align = ref<string>(); // 表头对齐方式 const headerAlign = ref<string>(); // 对应列的宽度 const columnWidth = ref<string | number>(parseWidth(props.width)); // 对应列的最小宽度 const columnMinWidth = ref<string | number>(parseMinWidth(props.minWidth)); // computed // 列的父级 const columnParent = computed(() => { let parent: ColumnParent = vm.vnode.vParent || vm.parent; // 没有表格id 没有列id while (parent && !parent.tableId && !parent.columnId) { parent = parent.vnode.vParent || parent.parent; } return parent; }); // 是否有列数据 const hasTreeColumn = computed<boolean>(() => { const { store }: any = vm.parent; // 没有 store if (!store) { return false; } const { treeData } = store.states; const treeDataValue = treeData.value; return treeDataValue && Object.keys(treeDataValue).length > 0; }); // methods // 获取props值 const getPropsData = (...propsKey: unknown[]) => { return propsKey.reduce((prev: TableColumnCtx, cur) => { // 数组 if (Array.isArray(cur)) { cur.forEach((key) => { prev[key] = props[key]; }); } return prev; }, {}); }; // 检查子列表 const checkSubColumn = (children: TableColumn | TableColumn[]) => { // 数组 if (Array.isArray(children)) { children.forEach((child) => check(child)); } // 其他 else { check(children); } // 检查是否是列表组件 function check(item: TableColumn) { if (item?.type?.name === `${prefixCls}-column`) { item.vParent = vm; } } }; // 列渲染 const columnRender = (column: TableColumnCtx) => { // renderHeader 属性不推荐使用。 // 不是多选框 if ( !props.renderHeader && column.type !== 'selection' && column.type !== 'index' ) { column.renderHeader = (scope) => { vm.columnConfig.value['label']; // 是否有头部插槽 const renderHeader = slots.header; return renderHeader ? renderHeader(scope) : column.label; }; } // 渲染行函数 let originRenderCell = column.renderCell; const hasTreeColumnValue = hasTreeColumn.value; // 可展开行 if (column.type === 'expand') { // 渲染行 column.renderCell = (data) => { return h( 'div', { class: 'cell', }, [originRenderCell(data)] ); }; // 展开的内容 parentDom.value.renderExpanded = (data) => { return slots.default ? slots.default(data) : slots.default; }; } // 其他状态 else { originRenderCell = originRenderCell || defaultRenderCell; // 渲染行 column.renderCell = (data: RenderRowData) => { let children = null; // 有默认插槽 if (slots.default) { // 设置vnode const vnode = slots.default(data); // 判断是否是注释 children = vnode.some((v) => v.type !== Comment) ? vnode : originRenderCell(data); } // 不是插槽 else { children = originRenderCell(data); } // 列数据 const shouldCreatePlaceholder = hasTreeColumnValue && data.cellIndex === 0; // 列的占位符-用于展示树形数据时,树节点的缩进 const prefix = treeCellPrefix(data, shouldCreatePlaceholder); // props const props = { class: 'cell', style: {}, }; // 当内容过长被隐藏时显示 tooltip if (column.showOverflowTooltip) { props.class = `${props.class} ${prefixCls}-tooltip`; props.style = { width: `${ (data.column.columnWidth || Number(data.column.width)) - 1 }px`, }; } // 检查子列表 checkSubColumn(children); return h('div', props, [prefix, children]); }; } return column; }; // 设置列宽度 const setColumnWidth = (column: TableColumnCtx) => { if (columnWidth.value) { column.width = columnWidth.value; } // 最小宽度 if (columnMinWidth.value) { column.minWidth = columnMinWidth.value; } // 没有设置最小宽度,默认最小宽度 80 if (!column.minWidth) { column.minWidth = 80; } // 列宽度 minWidth 或者 width column.columnWidth = Number( column.width === undefined ? column.minWidth : column.width ); return column; }; // 设置列 props const setColumnProps = (column: TableColumnCtx) => { // 对应列的类型 const type = column.type; // 不应覆盖的值 const source = cellForced[type] || {}; // 替换列 column 对象的参数 Object.keys(source).forEach((prop) => { // 获取值 const value = source[prop]; if (prop !== 'className' && value !== undefined) { column[prop] = value; } }); // 有对应的class 多选 | 展开 const className = getDefaultClassName(type); // 有对应的class if (className) { column.className = column.className ? `${column.className} ${className}` : className; } return column; }; // 获取列节点index const getColumnDomIndex = (children: HTMLElement[], el) => { return Array.prototype.indexOf.call(children, el); }; // watch // 同步监听 对齐方向 watchEffect(() => { align.value = props.align ? `is-${props.align}` : ''; return align.value; }); // 同步监听 表头对齐方式 watchEffect(() => { headerAlign.value = props.headerAlign ? `is-${props.headerAlign}` : align.value; return headerAlign.value; }); return { // data columnId, isSubColumn, align, headerAlign, // computed columnParent, // methods getPropsData, getColumnDomIndex, columnRender, setColumnWidth, setColumnProps, }; } export default useRender;