盘一下那些使用ant-design-vue组件库的经验和常见问题,包括v1、v3版本
1. v1版本
使用的是ant-design-vue@1.7.8 + vue@2.6.14 + vue-cli@5
1.1. 按需引入
1.1.1. 组件按需引入
修改babel.config.js
文件,配置 babel-plugin-import
module.exports = {
plugins: [
[
'import',
{
'libraryName': 'ant-design-vue',
'libraryDirectory': 'es',
'style': true // `style: true` 会加载 less 文件
}
]
]
}
src/vendor/ant-design.js
import Vue from 'vue'
import {
// Base,
// Affix,
// Anchor,
// AutoComplete,
Alert,
// Avatar,
// BackTop,
// Badge,
Breadcrumb,
Button,
// Calendar,
Card,
// Collapse,
// Carousel,
Cascader,
Checkbox,
Col,
DatePicker,
Divider,
Dropdown,
// Form,
FormModel,
Icon,
Input,
InputNumber,
// Layout,
List,
// LocaleProvider,
message,
Menu,
// Mentions,
Modal,
notification,
Pagination,
// Popconfirm,
// Popover,
// Progress,
Radio,
// Rate,
Row,
Select,
// Slider,
Spin,
// Statistic,
Steps,
// Switch,
Table,
Transfer,
Tree,
// TreeSelect,
Tabs,
Tag,
// TimePicker,
// Timeline,
Tooltip,
Upload,
// Drawer,
// Skeleton,
// Comment,
ConfigProvider,
Empty,
// Result,
// Descriptions,
// PageHeader,
Space,
version
} from 'ant-design-vue'
const components = [
// Base,
// Affix,
// Anchor,
// AutoComplete,
Alert,
// Avatar,
// BackTop,
// Badge,
Breadcrumb,
Button,
// Calendar,
Card,
// Collapse,
// Carousel,
Cascader,
Checkbox,
Col,
DatePicker,
Divider,
Dropdown,
// Form,
FormModel,
Icon,
Input,
InputNumber,
// Layout,
List,
// LocaleProvider,
Menu,
// Mentions,
Modal,
Pagination,
// Popconfirm,
// Popover,
// Progress,
Radio,
// Rate,
Row,
Select,
// Slider,
Spin,
// Statistic,
Steps,
// Switch,
Table,
Transfer,
Tree,
// TreeSelect,
Tabs,
Tag,
// TimePicker,
// Timeline,
Tooltip,
Upload,
// Drawer,
// Skeleton,
// Comment,
ConfigProvider,
Empty,
// Result,
// Descriptions,
// PageHeader,
Space
]
export default {
/**
* Vue use注册
* @param {Object} Vue
*/
install: function() {
components.map(function(component) {
Vue.use(component)
})
Vue.prototype.$message = message
Vue.prototype.$notification = notification
Vue.prototype.$info = Modal.info
Vue.prototype.$success = Modal.success
Vue.prototype.$error = Modal.error
Vue.prototype.$warning = Modal.warning
Vue.prototype.$confirm = Modal.confirm
Vue.prototype.$destroyAll = Modal.destroyAll
},
version
}
process.env.NODE_ENV !== 'production' && console.warn('[Antd] Antd使用按需加载, 若缺失, 请到此处修改.')
在main.js中引入
import Antdv from '@/vendor/ant-design'
Vue.use(Antdv)
1.1.2. 图标按需引入
处理1.2.0 之后全量引入了所有图标,bundle体积过大的问题
大概思路是自己搞一个icon引入文件,用别名把icon的默认库替换一下
如果打包报错:查看alias配置以及ant-icons.js导出是否正确
vue.config.js
module.exports = {
configureWebpack: {
resolve: {
alias: {
'@': resolve('src'),
// 大概思路是自己搞一个icon引入文件,用别名把icon的默认库替换一下
// @see https://github.com/ant-design/ant-design/issues/12011
'@ant-design/icons/lib/dist$': resolve('./src/vendor/ant-icons.js')
}
}
}
}
src/vendor/ant-icons.js
// export what antd other components need
export { default as CloseOutline } from '@ant-design/icons/lib/outline/CloseOutline'
export { default as CheckOutline } from '@ant-design/icons/lib/outline/CheckOutline'
export { default as LoadingOutline } from '@ant-design/icons/lib/outline/LoadingOutline'
export { default as CheckCircleOutline } from '@ant-design/icons/lib/outline/CheckCircleOutline'
export { default as InfoCircleOutline } from '@ant-design/icons/lib/outline/InfoCircleOutline'
export { default as CloseCircleOutline } from '@ant-design/icons/lib/outline/CloseCircleOutline'
export { default as ExclamationCircleOutline } from '@ant-design/icons/lib/outline/ExclamationCircleOutline'
export { default as CheckCircleFill } from '@ant-design/icons/lib/fill/CheckCircleFill'
export { default as InfoCircleFill } from '@ant-design/icons/lib/fill/InfoCircleFill'
export { default as CloseCircleFill } from '@ant-design/icons/lib/fill/CloseCircleFill'
export { default as ExclamationCircleFill } from '@ant-design/icons/lib/fill/ExclamationCircleFill'
export { default as UpOutline } from '@ant-design/icons/lib/outline/UpOutline'
export { default as DownOutline } from '@ant-design/icons/lib/outline/DownOutline'
export { default as LeftOutline } from '@ant-design/icons/lib/outline/LeftOutline'
export { default as RightOutline } from '@ant-design/icons/lib/outline/RightOutline'
export { default as RedoOutline } from '@ant-design/icons/lib/outline/RedoOutline'
export { default as CalendarOutline } from '@ant-design/icons/lib/outline/CalendarOutline'
export { default as SearchOutline } from '@ant-design/icons/lib/outline/SearchOutline'
export { default as BarsOutline } from '@ant-design/icons/lib/outline/BarsOutline'
export { default as StarFill } from '@ant-design/icons/lib/fill/StarFill'
export { default as FilterOutline } from '@ant-design/icons/lib/outline/FilterOutline'
export { default as CaretUpOutline } from '@ant-design/icons/lib/outline/CaretUpOutline'
export { default as CaretDownOutline } from '@ant-design/icons/lib/outline/CaretDownOutline'
export { default as PlusOutline } from '@ant-design/icons/lib/outline/PlusOutline'
export { default as FileOutline } from '@ant-design/icons/lib/outline/FileOutline'
export { default as FolderOpenOutline } from '@ant-design/icons/lib/outline/FolderOpenOutline'
export { default as FolderOutline } from '@ant-design/icons/lib/outline/FolderOutline'
export { default as PaperClipOutline } from '@ant-design/icons/lib/outline/PaperClipOutline'
export { default as PictureOutline } from '@ant-design/icons/lib/outline/PictureOutline'
export { default as EyeOutline } from '@ant-design/icons/lib/outline/EyeOutline'
export { default as DeleteOutline } from '@ant-design/icons/lib/outline/DeleteOutline'
export { default as UploadOutline } from '@ant-design/icons/lib/outline/uploadOutline'
export { default as EllipsisOutline } from '@ant-design/icons/lib/outline/EllipsisOutline'
// export what you need
// @see node_modules/@ant-design/icons/lib/index.es.js
export { default as LockOutline } from '@ant-design/icons/lib/outline/LockOutline'
export { default as InboxOutline } from '@ant-design/icons/lib/outline/InboxOutline'
export { default as UserOutline } from '@ant-design/icons/lib/outline/UserOutline'
export { default as RollbackOutline } from '@ant-design/icons/lib/outline/RollbackOutline'
export { default as PlusSquareOutline } from '@ant-design/icons/lib/outline/PlusSquareOutline'
export { default as MinusSquareOutline } from '@ant-design/icons/lib/outline/MinusSquareOutline'
export { default as ArrowDownOutline } from '@ant-design/icons/lib/outline/ArrowDownOutline'
export { default as EditOutline } from '@ant-design/icons/lib/outline/EditOutline'
process.env.NODE_ENV !== 'production' && console.warn('[Antd] Icon使用按需加载, 若缺失, 请到此处修改.')
1.2. 自定义主题色
vue.config.js
module.exports = {
css: {
loaderOptions: {
less: {
lessOptions: {
// If you are using less-loader@5 please spread the lessOptions to options directly
modifyVars: {
'primary-color': '#1FCAC4'
},
javascriptEnabled: true
}
}
}
}
}
1.3. 表格高度自适应
使用vue自定义指令实现
const install = function(Vue) {
Vue.directive('ant-height-adaptive-table', adaptive)
}
if (window.Vue) {
window['ant-height-adaptive-table'] = adaptive
Vue.use(install); // eslint-disable-line
}
/**
* How to use
* <el-table height="100px" v-el-height-adaptive-table="{bottomOffset: 30}">...</el-table>
* el-table height is must be set
* bottomOffset: 30(default) // The height of the table from the bottom of the page.
*/
const doResize = (el, binding, vnode) => {
const { componentInstance: $table } = vnode
const { value } = binding
const bottomOffset = (value && value.bottomOffset) || 30
if (!$table) return
const $tableHead = el.querySelector('.ant-table-thead') || { clientHeight: 0 }
const top = el.getBoundingClientRect().top
if (top === 0) return
const height = window.innerHeight - top - $tableHead.clientHeight - bottomOffset
setTimeout(() => {
// 设置table/list的高度
const $tableBody = el.querySelector('.ant-table-body')
if (!$tableBody) return
$tableBody.style.height = height + 'px'
binding.value.setHeight(height)
}, 0)
}
export default {
bind(el, binding, vnode) {
el.resizeListener = debounce(() => {
doResize(el, binding, vnode)
}, 100)
// parameter 1 is must be "Element" type
window.addEventListener('resize', el.resizeListener)
vnode.componentInstance.$handleResize = function() {
return doResize(el, binding, vnode)
}
},
inserted(el, binding, vnode) {
doResize(el, binding, vnode)
},
unbind(el) {
window.removeEventListener('resize', el.resizeListener)
},
install
}
在组件中使用
<template>
<a-table
v-ant-height-adaptive-table="{bottomOffset: 105, setHeight: handleResizeTable}"
:scroll="{y: scrollY}"
/>
</template>
<script>
import antHeightAdaptiveTable from '@/directive/ant-table'
export default {
data() {
return {
scrollY: 300
}
},
directives: {
antHeightAdaptiveTable
},
methods: {
/**
* 响应式设置表格高度
* @param {Number} height 表格高度
*/
handleResizeTable(height) {
this.scrollY = height
}
}
}
</script>
1.4. 动态主题
不像v3版本提供了 CSS Variable 版本以支持动态切换主题能力,v1需要用到webpack-theme-color-replacer插件,通过动态生成引入主题色的CSS规则来达到样式的覆盖。
详情可以参考:vueComponent/ant-design-vue-pro
也可以查看另一篇文章:webpack下的动态主题实现方案 - Timeless's博客 (timelessq.com)
2. v3版本
使用的是ant-design-vue@3.2.15 + vue@3.2.45 + vite@4
2.1. 按需引入
需要用到vite插件:unplugin-vue-components
vite.config.ts
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import Components from 'unplugin-vue-components/vite'
import { AntDesignVueResolver } from 'unplugin-vue-components/resolvers'
// https://vitejs.dev/config/
export default defineConfig({
plugins: [
vue(),
Components({
resolvers: [
AntDesignVueResolver({
resolveIcons: true
})
],
dts: './src/components.d.ts'
})
]
})
2.2. 表格高度自适应
和v1版本类似,也是使用自定义指令,但是vue3的写法不太一样
import { debounce } from 'lodash'
import type { DirectiveBinding, VNodeTypes } from 'vue'
interface DirectiveElement extends HTMLElement {
resizeListener: any
}
/**
* How to use
* <el-table height="100px" v-el-height-adaptive-table="{bottomOffset: 30}">...</el-table>
* el-table height is must be set
* bottomOffset: 30(default) // The height of the table from the bottom of the page.
*/
const doResize = (el: HTMLElement, binding: DirectiveBinding, vnode: VNodeTypes) => {
const { value } = binding
const bottomOffset = (value && value.bottomOffset) || 65
const $header = el.querySelector('.ant-table-thead') || {
clientHeight: 0
}
const top = el.getBoundingClientRect().top
if (top === 0) return
let height = window.innerHeight - top - $header.clientHeight - bottomOffset
height = height < 200 ? 200 : height
setTimeout(() => {
// 设置table/list的高度
const $body = (el.querySelector('.ant-table-body') ||
el.querySelector('.ant-list .ant-spin-nested-loading') ||
el.querySelector('.ant-list .ant-row')) as HTMLElement
if (!$body) return
$body.style.height = Math.floor(height) + 'px'
binding.value.setHeight(Math.floor(height))
}, 0)
}
export default {
// 在绑定元素的 attribute 前
// 或事件监听器应用前调用
created(el: DirectiveElement, binding: DirectiveBinding, vnode: VNodeTypes) {
el.resizeListener = debounce(() => {
doResize(el, binding, vnode)
}, 100)
// parameter 1 is must be "Element" type
window.addEventListener('resize', el.resizeListener)
},
// 在绑定元素的父组件
// 及他自己的所有子节点都挂载完成后调用
mounted(el: DirectiveElement, binding: DirectiveBinding, vnode: VNodeTypes) {
doResize(el, binding, vnode)
},
/**
* 在绑定元素的父组件
* 及他自己的所有子节点都更新后调用
* @summary 函数防抖处理因组件尺寸变化,视图未改变完成,就触发计算高度不正确的问题
*/
updated: debounce((el, binding, vnode) => {
doResize(el, binding, vnode)
}, 100),
// 绑定元素的父组件卸载后调用
unmounted(el: DirectiveElement) {
window.removeEventListener('resize', el.resizeListener)
}
}
还没有评论,快来抢第一吧