前言:作为一个刚入行没多久的菜鸟前端,之前一直使用的是ElementUI和iView提供的表格,但是某些场景下这两个框架提供的表格组件并不能很好的满足需求(当然,也可能是本人能力有限)。而ag-grid给我的感觉是相当惊喜的,上手了一周多的时间,用到的功能也只有冰山一角,但是已经能体会到这个组件的强大了,印证了官网的标语(The Best JavaScript Grid in the World)。这篇文章旨在记录分享下自己的使用过程,也希望能给刚接触这个组件的朋友一些参考。
引入
1.使用组件的第一步当然是引入啦
<!-- npm版 -->
npm install ag-grid-community ag-grid-vue --save-dev
<!--如果引入后运行项目报错,可以按照报错提示安装对应依赖,我个人是下面两个都需要安装-->
npm install --save vue-property-decorator
npm install --save vue-class-component
<!-- yarn版 -->
yarn add ag-grid-community ag-grid-vue -D
yarn add vue-property-decorator
yarn add vue-class-component
2.引入样式文件,放在main.js中全局引入
import "ag-grid-community/dist/styles/ag-grid.css";
import "ag-grid-community/dist/styles/ag-theme-balham.css";
3.关于自定义主题样式,水平有限暂时没有弄明白官方的用法(等我弄明白了就来把这块补上),目前是引入CSS文件,使用类名覆盖
<!--main.js中引入自己新建的css文件-->
import "@assets/scss/ag-grid.scss";
使用
1.简单demo
<template>
<ag-grid-vue
style="height:500px;width:100%"
class="ag-theme-balham"
:columnDefs="columnDefs"
:rowData="rowData"
:gridOptions="gridOptions"
@grid-ready="onGridReady"
></ag-grid-vue>
<!--ag-theme-balham这个类名是组件提供的默认主题-->
</template>
<script>
export default {
data(){
gridApi: {}, //表格方法
columnApi: {}, //列方法
gridOptions: {}, //ag-grid配置项
rowData:[],//表格中填充的数据
columnDefs:[//列配置,更多配置可以查询官网
{
headerName: "类型",
field: "type",
width: 160
},
{
headerName: "开始时间",
field: "beginTime",
width: 240
},
{
headerName: "渠道",
field: "channelName",
width: 200
}
]
},
beforeMount(){
this.gridOptions = {
//表格配置项
rowHeight: 40,
headerHeight: 40,
};
},
method:{
/**
* @description: 表格准备就绪 挂载属性及api
* @param {Object} params - 表格实例
* @return {*}
*/
onGridReady(params) {
this.gridApi = params.api;
this.columnApi = params.columnApi;
// 这时就可以通过gridApi调用ag-grid的传统方法了
this.gridApi.sizeColumnsToFit();
<!-- 可以将params打印出来会让你对表格有个更直观的理解 -->
},
}
}
</script>
2.布局尺寸
ag-grid支持直接使用样式定义尺寸,也支持自动高度,需要注意的是自动高度下不支持设置最大高度,更多的布局方式请移步文档
<!--如果是初始化就设为自动高度,可以直接通过配置项设置-->
beforeMount(){
this.gridOptions = {
//表格配置项
domLayout:'autoHeight'
};
},
<!--如果是页面交互需要在特定场景下自动高度,可以通过提供的api来设置-->
this.gridApi.setDomLayout("autoHeight")
3.缩放
窗口尺寸变化后需要调用sizeColumnsToFit这个方法让表格调整大小,建议使用mixin混入公共代码或者将表格封装为组件,省的每次在使用表格时都要写一遍
window.addEventListener("resize",()=>{
this.gridOptions.api.sizeColumnsToFit()
})
4.自定义表格内容
单纯的文字过滤可以使用valueGetter这个属性,这里就不多介绍了。而很多时候表格不单单只是单纯的字段展示,也会有一些点击交互之类的,所以我们需要去定义我们想要的内容,ag-grid提供了cellRenderer以及cellRendererFrameWork两个属性,我用的是后者,以下代码基于最开始的简单demo,demo中无关代码已省略
<script>
import Vue from "vue" //这里需要引入Vue
let renderType = Vue.extend({ //创建一个新的实例作为组件使用
<!--在这个组件中可以直接使用params这个变量-->
<!--params为ag-grid封装好的节点对象,里面包含有相关信息-->
template:`<div @click="sayHello">{{params.data.type}}</div>`
methods:{
sayHello(){
console.log(this.params)//打印出来你就知道是啥了
this.params.context.componentParent.sayHi()//调用父组件中的方法
//this.params.context.componentParent指向的就是父组件
}
}
})
export default {
data(){
columnDefs:[//列配置,更多配置可以查询官网
{
headerName: "类型",
field: "type",
width: 160,
cellRendererFrameWork:renderType //!!声明使用的组件!!
},
{
headerName: "开始时间",
field: "beginTime",
width: 240
},
{
headerName: "渠道",
field: "channelName",
width: 200
}
]
},
beforeMount(){
this.gridOptions = {
context: { componentParent: this },//通过这个属性建立了上下文引用
//说人话就是可以在自己声明的组件里调用到父组件的方法和属性了
}
}
methods:{
sayHi(){
console.log('我是父组件里的方法')
}
}
}
</script>
5.tooltip提示
依然基于demo,省去无关代码
<template>
<ag-grid-vue
style="height:500px;width:100%"
class="ag-theme-balham"
:columnDefs="columnDefs"
:rowData="rowData"
:gridOptions="gridOptions"
@grid-ready="onGridReady"
:tooltipShowDelay="500" //tooltip延迟时间 单位ms
:frameworkComponents="frameworkComponents" //声明表格要用到的组件
></ag-grid-vue>
</template>
<script>
let tooltipValueGetter = function(params) {
return { value: params.value };//params为节点信息
};
export default{
components:{
renderTooltip: {
template: `<div :style="{display:params.value.value?'block':'none',color:'#333'}" class="ag-tooltip">{{params.value.value}}</div>`
}
},
data(){
return{
columnDefs:[//列配置,更多配置可以查询官网
{
headerName: "类型",
field: "type",
width: 160,
tooltipComponent: "renderTooltip", //声明使用的组件
tooltipValueGetter: tooltipValueGetter //声明tooltip中使用的字段
},
{
headerName: "开始时间",
field: "beginTime",
width: 240
},
{
headerName: "渠道",
field: "channelName",
width: 200
}
],
frameworkComponents:{},
}
},
beforeMount(){
this.frameworkComponents = { renderTooltip: "renderTooltip" }; //声明使用到的组件,组件本身需要写在components中
}
}
</script>
关于frameworkComponents我的理解是先从components中收集好需要的组件,然后提供给每一列去自由选择
6.实现类似element表格固定列的阴影效果
当内容过长且单侧或两侧固定时,表格会提供滚动条,但是ag-grid并没有提供类似element表格的交互效果,只是在固定列(左/右)侧提供了两条实线作为边界,所以我根据element表格的阴影效果逻辑,简单粗暴的通过dom对ag-grid进行了一点改动。下图为element表格的效果。
当有固定列时,ag-grid会将其他列放入一个容器,对比容器宽度和计算其他列的总宽度,就可以知道当前容器内是否出现滚动条,再通过监听容器的scroll事件去判断当前的滚动情况从而控制阴影的显示。
温馨提示:觉得下面代码太长不想看的可以根据tip中的内容对代码进行改动后直接复制粘贴
tip:以下代码为单页面多个表格的情况,所以代码中表格的columnDefs属性绑定的值是一个二维数组并且使用querySelectorAll选择器。如果页面上只有一个表格,将columnDefs属性绑定的值改为一维数组,然后使用querySelector,最后将下面代码中的‘[i]’全部删除即可。tableResize方法请放在window的resize事件中执行。
<template>
<ag-grid-vue
style="height:500px;width:100%"
class="ag-theme-balham"
:columnDefs="columnDefs[0]" //二维数组
:rowData="rowData"
:gridOptions="gridOptions"
@grid-ready="onGridReady"
></ag-grid-vue>
</template>
tableResize() {
let wrap = document.querySelectorAll(".ag-center-cols-viewport");//容器
let left = document.querySelectorAll(".ag-pinned-left-cols-container");//左侧固定列节点
let right = document.querySelectorAll(".ag-pinned-right-cols-container");//右侧固定列节点
let leftHeader = document.querySelectorAll(".ag-pinned-left-header");//左侧固定列表头节点
let rightHeader = document.querySelectorAll(".ag-pinned-right-header");//右侧固定列表头节点
if (
wrap &&
left &&
right &&
leftHeader &&
rightHeader
) {
/*
动态设置中间可滚动区的阴影效果
*/
wrap.forEach((n, i) => {
if (Array.isArray(this.columnDefs[i])) {
let containerWidth = 0;
this.columnDefs[i].forEach(item => { //计算出非固定列的宽度总和
if (!item.pinned) { //固定列会有pinned这个属性
if (item.width) {
containerWidth += item.width;
} else if (item.minWidth) {
containerWidth += item.minWidth;
}
}
});
let handleFunction = () => {
if (wrap[i].offsetWidth >= containerWidth) {
left[i].style.boxShadow = "none";
right[i].style.boxShadow = "none";
leftHeader[i].style.boxShadow = "none";
rightHeader[i].style.boxShadow = "none";
} else {
if (wrap[i].scrollLeft == 0) {
right[i].style.boxShadow = "-3px 0px 4px 0px #bbbbbb";
rightHeader[i].style.boxShadow = "-3px 0px 4px 0px #bbbbbb";
right[i].style.zIndex = "10";
left[i].style.boxShadow = "none";
leftHeader[i].style.boxShadow = "none";
} else if (
wrap[i].scrollLeft > 0 &&
wrap[i].scrollLeft < containerWidth - wrap[i].offsetWidth
) {
right[i].style.boxShadow = "-3px 0px 4px 0px #bbbbbb";
rightHeader[i].style.boxShadow = "-3px 0px 4px 0px #bbbbbb";
right[i].style.zIndex = "10";
left[i].style.boxShadow = "3px 0px 4px 0px #bbbbbb";
leftHeader[i].style.boxShadow = "3px 0px 4px 0px #bbbbbb";
left[i].style.zIndex = "10";
} else if (
wrap[i].scrollLeft ==
containerWidth - wrap[i].offsetWidth
) {
left[i].style.boxShadow = "3px 0px 4px 0px #bbbbbb";
leftHeader[i].style.boxShadow = "3px 0px 4px 0px #bbbbbb";
left[i].style.zIndex = "10";
right[i].style.boxShadow = "none";
rightHeader[i].style.boxShadow = "none";
}
}
};
handleFunction(); //窗口尺寸变化
wrap[i].onscroll = () => {
handleFunction();
};
}
});
}
}
总结
以上就是我一周以来上手ag-grid的一些拙见,通过这个表格的使用也促进了我对vue的理解,个人感觉是收获颇丰,这种获得知识的满足感大概就是学习的快乐吧。码字不易,如果觉得有帮助的可以点个赞,以上内容有错误或者不足的也欢迎各位指出,共同进步。