文章目录
安装脚手架工具使用Vue CLI新建项目下载ant-design-vue,ant-design-vue@2.1.6修改main.js,完整引入ant-design-vue所有组件及样式修改HelloWorld.vue,使用Antd的Table组件修改HelloWorld.vue,使用Antd的Table组件$slotsTable组件相关源码安装脚手架工具
npm install -g @vue/cli
查看@vue/cli
版本,vue -V
。
使用Vue CLI新建项目
vue create antd-demo
下载ant-design-vue,ant-design-vue@2.1.6
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>
:columns="columns"
,columns
是一个数组,用于指定列头dataIndex
值依次是:name
、age
和address
,与dataSource
每项的name
、age
和address
对应。title
,dataIndex
值对应的列头名称name
,对应的列头名称是姓名
age
,对应的列头名称是年龄
address
,对应的列头名称是地址
key
,Vue需要的key,如果已经设置了唯一的dataIndex
,可以忽略这个属性:dataSource=dataSource
,指定数据源dataSource
是一个数组每项的name
、age
和address
,与columns
里dataIndex
的值:name
、age
和address
相对应
修改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-tagv-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里: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');
现在我们修改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>
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;}
只有满足条件(column[key] === undefined && $slots[name])
,才能使用作用域插槽来自定义表头。本例中,dataIndex:'name'
想自定义表头,所以不能定义title
属性,而是在slots
属性中定义了title
属性。
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 /ant-design/ant-design/issues/1202if (isInvalidRenderCellText(text)) {text = null;}if (transformCellText) {text = transformCellText({text, column, record, index });}const indentText = expandIcon ? (<spanstyle={{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,// 如果有宽度,增加断行处理// /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>);}
其中,customRender
是渲染函数,用来对表中的值进行自定义渲染。该函数接受4个参数,分别是text
、record
、index
和column
。
antd官网也有customRender
的相关说明,如下,