如何使用ant-design-vue的Table組件
安裝腳手架工具
npm install -g @vue/cli
查看@vue/cli版本,vue -V。
使用Vue CLI新建項(xiàng)目
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: '西湖區(qū)湖底公園1號(hào)', ? ? ? ? ? }, ? ? ? ? ? { ? ? ? ? ? ? key: '2', ? ? ? ? ? ? name: '胡彥祖', ? ? ? ? ? ? age: 42, ? ? ? ? ? ? address: '西湖區(qū)湖底公園1號(hào)', ? ? ? ? ? }, ? ? ? ? ], ? ? ? ? columns: [ ? ? ? ? ? { ? ? ? ? ? ? title: '姓名', ? ? ? ? ? ? dataIndex: 'name', ? ? ? ? ? ? key: 'name', ? ? ? ? ? }, ? ? ? ? ? { ? ? ? ? ? ? title: '年齡', ? ? ? ? ? ? dataIndex: 'age', ? ? ? ? ? ? key: 'age', ? ? ? ? ? }, ? ? ? ? ? { ? ? ? ? ? ? title: '住址', ? ? ? ? ? ? dataIndex: 'address', ? ? ? ? ? ? key: 'address', ? ? ? ? ? }, ? ? ? ? ], ? ? ? }; ? ? }, ? }; </script>
:columns="columns"
,columns是一個(gè)數(shù)組,用于指定列頭dataIndex
值依次是:name、age和address,與dataSource每項(xiàng)的name、age和address對(duì)應(yīng)。title
,dataIndex值對(duì)應(yīng)的列頭名稱(chēng)name
,對(duì)應(yīng)的列頭名稱(chēng)是姓名age
,對(duì)應(yīng)的列頭名稱(chēng)是年齡address
,對(duì)應(yīng)的列頭名稱(chēng)是地址
key
,Vue需要的key,如果已經(jīng)設(shè)置了唯一的dataIndex,可以忽略這個(gè)屬性:dataSource=dataSource
,指定數(shù)據(jù)源dataSource
是一個(gè)數(shù)組- 每項(xiàng)的name、age和address,與columns里dataIndex的值:name、age和address相對(duì)應(yīng)
修改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里:data-source與:dataSource是等效的。
要使用slots自定義樣式,就有必要了解下Vue里的$slots和Table組件的源碼。
$slots
插槽內(nèi)容可以在this.$slots中看到,舉個(gè)例子。
組件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');
現(xiàn)在我們修改base-layout.vue,使用this.$slots來(lái)訪問(wèn)插槽內(nèi)容。
<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組件相關(guān)源碼
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; }
只有滿(mǎn)足條件(column[key] === undefined && $slots[name]),才能使用作用域插槽來(lái)自定義表頭。本例中,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 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> ? ); }
其中,customRender是渲染函數(shù),用來(lái)對(duì)表中的值進(jìn)行自定義渲染。該函數(shù)接受4個(gè)參數(shù),分別是 text、 record、index和 column。
antd官網(wǎng)也有customRender的相關(guān)說(shuō)明,如下
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
使用vue.js開(kāi)發(fā)時(shí)一些注意事項(xiàng)
使用vue.js進(jìn)行項(xiàng)目的開(kāi)發(fā)已經(jīng)有了一定的時(shí)間,在任務(wù)的過(guò)程中以及和不同的開(kāi)發(fā)使用者交流中,逐漸對(duì)vue.js的使用心得有了一定的積累。本文主要給大家分享一些開(kāi)發(fā)時(shí)需要注意的事項(xiàng)2016-04-04Vue動(dòng)態(tài)組件component的深度使用說(shuō)明
這篇文章主要介紹了Vue動(dòng)態(tài)組件component的深度使用說(shuō)明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-04-04vue 組件內(nèi)獲取actions的response方式
今天小編就為大家分享一篇vue 組件內(nèi)獲取actions的response方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2019-11-11vue如何集成raphael.js中國(guó)地圖的方法示例
最近的數(shù)據(jù)統(tǒng)計(jì)項(xiàng)目中要用到中國(guó)地圖,也就是在地圖上動(dòng)態(tài)的顯示某個(gè)時(shí)間段某個(gè)省份地區(qū)的統(tǒng)計(jì)數(shù)據(jù),我們不需要flash,僅僅依靠raphael.js以及SVG圖像就可以完成地圖的交互操作。本文就給大家介紹了關(guān)于利用vue集成raphael.js中國(guó)地圖的相關(guān)資料,需要的朋友可以參考下。2017-08-08在vue框架下使用指令vue add element安裝element報(bào)錯(cuò)問(wèn)題
這篇文章主要介紹了在vue框架下使用指令vue add element安裝element報(bào)錯(cuò)問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-10-10基于vue和react的spa進(jìn)行按需加載的實(shí)現(xiàn)方法
這篇文章主要介紹了基于vue和react的spa進(jìn)行按需加載,需要的朋友可以參考下2018-09-09vue實(shí)現(xiàn)兩個(gè)組件之間數(shù)據(jù)共享和修改操作
這篇文章主要介紹了vue實(shí)現(xiàn)兩個(gè)組件之間數(shù)據(jù)共享和修改操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-11-11