使用ant-design-vue的Table组件

文章目录

        • 安装脚手架工具
        • 使用Vue CLI新建项目
        • 下载ant-design-vue,[email protected]
        • 修改main.js,完整引入ant-design-vue所有组件及样式
        • 修改HelloWorld.vue,使用Antd的Table组件
        • 修改HelloWorld.vue,使用Antd的Table组件
          • $slots
          • Table组件相关源码

安装脚手架工具

npm install -g @vue/cli

查看@vue/cli版本,vue -V

使用Vue CLI新建项目

vue create antd-demo

下载ant-design-vue,[email protected]

npm install ant-design-vue@next --save

修改main.js,完整引入ant-design-vue所有组件及样式

import { createApp } from 'vue'
import App from './App.vue'
import Antd from "ant-design-vue";
import "ant-design-vue/dist/antd.css";

createApp(App).use(Antd).mount('#app')

修改HelloWorld.vue,使用Antd的Table组件

<template>
  <a-table :dataSource="dataSource" :columns="columns" />
</template>

<script>
  export default {
    name:"Helloworld",
    setup() {
      return {
        dataSource: [
          {
            key: '1',
            name: '胡彦斌',
            age: 32,
            address: '西湖区湖底公园1号',
          },
          {
            key: '2',
            name: '胡彦祖',
            age: 42,
            address: '西湖区湖底公园1号',
          },
        ],

        columns: [
          {
            title: '姓名',
            dataIndex: 'name',
            key: 'name',
          },
          {
            title: '年龄',
            dataIndex: 'age',
            key: 'age',
          },
          {
            title: '住址',
            dataIndex: 'address',
            key: 'address',
          },
        ],
      };
    },
  };
</script>

使用ant-design-vue的Table组件_第1张图片
使用ant-design-vue的Table组件_第2张图片

  • :columns="columns"columns是一个数组,用于指定列头
    • dataIndex值依次是:nameageaddress,与dataSource每项的nameageaddress对应。
    • titledataIndex值对应的列头名称
      • name,对应的列头名称是姓名
      • age,对应的列头名称是年龄
      • address,对应的列头名称是地址
    • key,Vue需要的key,如果已经设置了唯一的dataIndex,可以忽略这个属性
  • :dataSource=dataSource,指定数据源
    • dataSource是一个数组
    • 每项的nameageaddress,与columnsdataIndex的值:nameageaddress相对应

修改HelloWorld.vue,使用Antd的Table组件

<template>
  <a-table :columns="columns" :data-source="data">
    <template #name="{ text }">
      <a>{{ text }}</a>
    </template>
    <template #customTitle>
      <span>
        <smile-outlined />
        Name
      </span>
    </template>
    <template #tags="{ text: tags }">
      <span>
        <a-tag
          v-for="tag in tags"
          :key="tag"
          :color="tag === 'loser' ? 'volcano' : tag.length > 5 ? 'geekblue' : 'green'"
        >
          {{ tag.toUpperCase() }}
        </a-tag>
      </span>
    </template>
    <template #action="{ record }">
      <span>
        <a>Invite 一 {{ record.name }}</a>
        <a-divider type="vertical" />
        <a>Delete</a>
        <a-divider type="vertical" />
        <a class="ant-dropdown-link">
          More actions
          <down-outlined />
        </a>
      </span>
    </template>
  </a-table>
</template>
<script lang="ts">
import { SmileOutlined, DownOutlined } from '@ant-design/icons-vue';
import { defineComponent } from 'vue';
const columns = [
  {
    dataIndex: 'name',
    key: 'name',
    slots: { title: 'customTitle', customRender: 'name' },
  },
  {
    title: 'Age',
    dataIndex: 'age',
    key: 'age',
  },
  {
    title: 'Address',
    dataIndex: 'address',
    key: 'address',
  },
  {
    title: 'Tags',
    key: 'tags',
    dataIndex: 'tags',
    slots: { customRender: 'tags' },
  },
  {
    title: 'Action',
    key: 'action',
    slots: { customRender: 'action' },
  },
];

const data = [
  {
    key: '1',
    name: 'John Brown',
    age: 32,
    address: 'New York No. 1 Lake Park',
    tags: ['nice', 'developer'],
  },
  {
    key: '2',
    name: 'Jim Green',
    age: 42,
    address: 'London No. 1 Lake Park',
    tags: ['loser'],
  },
  {
    key: '3',
    name: 'Joe Black',
    age: 32,
    address: 'Sidney No. 1 Lake Park',
    tags: ['cool', 'teacher'],
  },
];

export default defineComponent({
  setup() {
    return {
      data,
      columns,
    };
  },
  components: {
    SmileOutlined,
    DownOutlined,
  },
});
</script>

使用ant-design-vue的Table组件_第3张图片
注意哈,ant-design-vue Table里:data-source与:dataSource是等效的。

要使用slots自定义样式,就有必要了解下Vue里的$slots和Table组件的源码。

$slots

插槽内容可以在this.$slots中看到,举个例子。

  • 组件base-layout
<template>
    <header>
        <slot name="header"></slot>
    </header>
    <main>
        <slot name="default"></slot>
    </main>
    <footer>
        <slot name="footer"></slot>
    </footer>
</template>

<script>
export default {
    name:"base-layout"
}
</script>
  • App.vue
<template>
  <BaseLayout>
    <template #header>
      <p>Here is part one</p>
    </template>
    <template #default>
      <p>Here is part two</p>
    </template>
    <template #footer>
      <p>Here is part three</p>
    </template>
  </BaseLayout>
</template>

<script>
import BaseLayout from "./components/base-layout.vue";

export default {
  name: 'App',
  components: {
    BaseLayout 
  }
}
</script>

<style>
#app {
  font-family: Avenir, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
}
</style>
  • main.js
import { createApp } from 'vue'
import App from './App.vue'
import Antd from "ant-design-vue";
import "ant-design-vue/dist/antd.css";

createApp(App).use(Antd).mount('#app');

使用ant-design-vue的Table组件_第4张图片
现在我们修改base-layout.vue,使用this.$slots来访问插槽内容。

<template>
    <header>
        <slot name="header"></slot>
    </header>
    <main>
        <slot name="default"></slot>
    </main>
    <footer>
        <slot name="footer"></slot>
    </footer>
</template>

<script>
export default {
    name:"base-layout",
    mounted:function(){
        console.log(this);
        console.log(this.$slots);
        console.log(this.$slots.header);
        console.log(this.$slots.header());
        console.log(this.$slots.header()[0].el);
        console.log(this.$slots.default()[0].el);
        console.log(this.$slots.footer()[0].el);
    }
}
</script>

使用ant-design-vue的Table组件_第5张图片

Table组件相关源码
  • node_modules/ant-design-vue/es/table/index.js
updateColumns(cols = []) {
  const columns = [];
  const { $slots, $scopedSlots } = this;
  cols.forEach(col => {
    const { slots = {}, scopedSlots = {}, ...restProps } = col;
    const column = {
      ...restProps,
    };
    Object.keys(slots).forEach(key => {
      const name = slots[key];
      if (column[key] === undefined && $slots[name]) {
        column[key] = $slots[name].length === 1 ? $slots[name][0] : $slots[name];
      }
    });
    Object.keys(scopedSlots).forEach(key => {
      const name = scopedSlots[key];
      if (column[key] === undefined && $scopedSlots[name]) {
        column[key] = $scopedSlots[name];
      }
    });
    // if (slotScopeName && $scopedSlots[slotScopeName]) {
    //   column.customRender = column.customRender || $scopedSlots[slotScopeName]
    // }
    if (col.children) {
      column.children = this.updateColumns(column.children);
    }
    columns.push(column);
  });
  return columns;
}

使用ant-design-vue的Table组件_第6张图片

使用ant-design-vue的Table组件_第7张图片

只有满足条件(column[key] === undefined && $slots[name]),才能使用作用域插槽来自定义表头。本例中,dataIndex:'name'想自定义表头,所以不能定义title属性,而是在slots属性中定义了title属性。
使用ant-design-vue的Table组件_第8张图片

  • node_modules/ant-design-vue/es/vc-table/src/TableCell.js
render() {
  const {
    record,
    indentSize,
    prefixCls,
    indent,
    index,
    expandIcon,
    column,
    component: BodyCell,
  } = this;
  const { dataIndex, customRender, className = '' } = column;
  const { transformCellText } = this.table;
  // We should return undefined if no dataIndex is specified, but in order to
  // be compatible with object-path's behavior, we return the record object instead.
  let text;
  if (typeof dataIndex === 'number') {
    text = get(record, dataIndex);
  } else if (!dataIndex || dataIndex.length === 0) {
    text = record;
  } else {
    text = get(record, dataIndex);
  }
  let tdProps = {
    props: {},
    attrs: {},
    on: {
      click: this.handleClick,
    },
  };
  let colSpan;
  let rowSpan;

  if (customRender) {
    text = customRender(text, record, index, column);
    if (isInvalidRenderCellText(text)) {
      tdProps.attrs = text.attrs || {};
      tdProps.props = text.props || {};
      tdProps.class = text.class;
      tdProps.style = text.style;
      colSpan = tdProps.attrs.colSpan;
      rowSpan = tdProps.attrs.rowSpan;
      text = text.children;
    }
  }

  if (column.customCell) {
    tdProps = mergeProps(tdProps, column.customCell(record, index));
  }

  // Fix https://github.com/ant-design/ant-design/issues/1202
  if (isInvalidRenderCellText(text)) {
    text = null;
  }

  if (transformCellText) {
    text = transformCellText({ text, column, record, index });
  }

  const indentText = expandIcon ? (
    <span
      style={{ paddingLeft: `${indentSize * indent}px` }}
      class={`${prefixCls}-indent indent-level-${indent}`}
    />
  ) : null;

  if (rowSpan === 0 || colSpan === 0) {
    return null;
  }
  if (column.align) {
    tdProps.style = { textAlign: column.align, ...tdProps.style };
  }

  const cellClassName = classNames(className, column.class, {
    [`${prefixCls}-cell-ellipsis`]: !!column.ellipsis,
    // 如果有宽度,增加断行处理
    // https://github.com/ant-design/ant-design/issues/13825#issuecomment-449889241
    [`${prefixCls}-cell-break-word`]: !!column.width,
  });

  if (column.ellipsis) {
    if (typeof text === 'string') {
      tdProps.attrs.title = text;
    } else if (text) {
      // const { props: textProps } = text;
      // if (textProps && textProps.children && typeof textProps.children === 'string') {
      //   tdProps.attrs.title = textProps.children;
      // }
    }
  }

  return (
    <BodyCell class={cellClassName} {...tdProps}>
      {indentText}
      {expandIcon}
      {text}
    </BodyCell>
  );
}

使用ant-design-vue的Table组件_第9张图片
其中,customRender是渲染函数,用来对表中的进行自定义渲染。该函数接受4个参数,分别是 textrecordindexcolumn
使用ant-design-vue的Table组件_第10张图片
antd官网也有customRender的相关说明,如下,
使用ant-design-vue的Table组件_第11张图片

你可能感兴趣的:(Vue)