normal.vue 2.6 KB
<script>
import { get } from '../utils';
import { renderContext } from '../utils/vnode';

// 标题渲染
function headerRender(h, context, item) {
  const headerSlot = context.scopedSlots[`header-${item.prop}`];
  return function(scope) {
    // 自定义具名插槽
    if (headerSlot) {
      return headerSlot(scope);
    }
    // 自定义渲染函数
    if (item.header) {
      return item.header(item, h, scope);
    }
    // 默认取值
    return item.label;
  };
}

// 单元格渲染
function cellRender(h, context, item) {
  const cellSlot = context.scopedSlots[`cell-${item.prop}`];
  return function(scope) {
    const value = get(scope.row, item.prop);
    // 自定义具名插槽
    if (cellSlot) {
      return cellSlot({
        item,
        value,
        index: scope.$index,
        ...scope,
      });
    }
    // 自定义渲染函数
    if (item.render) {
      return item.render(value, scope.row, h, scope.$index);
    }
    // 默认取值
    return get(scope.row, item.prop);
  };
}

// 跟进columns生成列
function createElTableColumns(h, context, columns) {
  return columns.map((item, index) => {
    const { attrs, on, ...props } = item;
    // 处理插槽
    const scopedSlots = {
      header: headerRender(h, context, item),
      default: cellRender(h, context, item),
    };
    return h('el-table-column', { key: index, attrs, props, on, scopedSlots });
  });
}

export default {
  name: 'TableNormal',
  functional: true,
  render(h, context) {
    const props = context.props || {};
    let scopedSlots = context.scopedSlots || {};
    const columns = props.columns || [];
    // 通过columns快速生成el-table-column
    const elTableColumns = createElTableColumns(h, context, columns);
    // 前置插槽
    const prependSlot = scopedSlots.prepend ? scopedSlots.prepend() : '';
    // 左侧插槽
    const leftSlot = scopedSlots.left ? scopedSlots.left() : '';
    // 默认插槽
    const defaultSlot = scopedSlots.default ? scopedSlots.default() : '';
    delete scopedSlots.default;
    // 右侧插槽
    const rightSlot = scopedSlots.right ? scopedSlots.right() : '';
    // 后置插槽
    const appendSlot = scopedSlots.append ? scopedSlots.append() : '';
    // 渲染组件时移除当前组件特有的props,避免透传不必要的参数
    delete context.columns;
    // 兼容旧版value属性
    if (context.props.value && !context.props.data) {
      context.props.data = context.props.value;
      delete context.props.value;
    }
    return h('el-table', renderContext(context), [prependSlot, leftSlot, ...elTableColumns, defaultSlot, rightSlot, appendSlot]);
  },
};
</script>