1.对话框
当打开的对话框页面元素众多,俨然一个iframe页面时,可以做2个优化:
- 滚动条:对话框去滚动,当对话框内容过多时,把滚动条控制在对话框内部,避免出现页面级的滚动条
- 标题栏:优化对话框标题样式,为其添加一个背景色,使之看上去更像一个iframe页面
实现思路:
- 把滚动条控制在对话框内部,要点在于给内容区域设定一个合适的高度,经测试,这个高度为:
页面高度(100vh) - marign-top(15vh) - marign-bottom(50px) - 对话框标题高度(54px)
- 去除内容区默认的默认的padding
- 重置对话框标题背景色
- 如果页面元素不足以撑起整个容器,可以把提交按钮固定的底部,防止页面过于空旷
/* 重置对话框标题背景色 */
.el-dialog__header {
background-color: #2c3e50 !important;
}
/* 重置对话框标题字体颜色 */
.el-dialog__header .el-dialog__title {
color: #fff !important;
}
/* 去除内容区默认padding */
.el-dialog__body{
padding:0 !important;
}
<!-- 弹框区域 开始 -->
<el-dialog title="对话框标题" :visible.sync="dialogVisible" width="80%" :close-on-click-modal="false" :before-close="dialogBeforeClose">
<!-- calc(85vh - 104px) -->
<div style="height:calc(85vh - 50px - 54px);">
<vue-scroll>
<div style="padding:10px;">
</div>
</vue-scroll>
</div>
</el-dialog>
<!-- 弹框区域 结束 -->
2.列宽自适应
无论是Element-UI中的table组件,还是专业vxe-table表格插件,都无法做到完美的列宽自适应,更不用说第三方插件。一切还得自己来,解决思路如下:
- 表格的每一列默认均分宽度,如果某一列设定了具体的宽度,则其他列均分剩下的宽度
- width和min-width都具有响应式特定,值发生变化表格会重新布局
- 列建议禁止换行,因为会造成每行高度不一致,影响观感 ,例如:通过设定列标签的 class-name 属性来设定列样式
- 宽度固定的列,例如时间,姓名等等,建议设定width,但是不能所有的列都是固定宽度
- 宽度不固定的列,例如地址,可以根据表头或者列内容来设定最小宽度
- 列的最大宽度由列标题和列内容决定,可以封装一个过滤器,传入列字段和标题,来输出最大宽度
- 宽度计算涉及字体大小,padding,有时候还需要设定最大值与最小值
//过滤器代码
//闭包 传入当前环境的this
(function (global, factory) {
//1.先判断当前环境是否支持CommonJS规范(node.js)
if (typeof exports == 'object' && typeof module !== 'undefined') {
console.log('CommonJS规范')
module.exports = factory()
} else if (typeof define == 'function' && define.amd) {//2.再判断是否支持AMD规范(require.js)
console.log('AMD规范')
define(factory)
} else {
console.log('script标签引入')
if(this.Vue){
//自动执行安装
Vue.use(factory())
}
}
}(this, function () {
return {
//插件安装方法
install: function (Vue) {
if (!Vue) {
return
}
//过滤器 求出表格列的最大宽度
Vue.filter('maxWidthForColumn', function (tableData = [], prop = '',title='',option = {}) {
//默认值设定
if(!option.font_size){
option.font_size = 12
}
if(!option.padding){
option.padding = 10
}
if(!option.min){
option.min = 80
}
if(!option.max){
option.max = 300
}
//是否根据内容确认列宽,否则使用表头确认列表
if(!option.fit_content){
option.fit_content = false
}
//计算表头占位宽度
var title_width = getTextWidth(title)
//是否根据内容确认列宽
if(option.fit_content){
//获取字符串集合(列内容,不包含列表头)
var text_list = tableData.map(item => {
return item[prop]
})
//计算字符串集合的最大宽度
var content_max_width = getMaxWidthByArray(text_list)
}else{
//忽略内容宽度
var content_max_width = option.min
}
//列表头和列表体 取最大值
//console.log('列表体与表头',content_max_width,title_width)
var target_width = content_max_width > title_width? content_max_width:title_width
//加上左右padding 20px
target_width += (option.padding*2)
//console.log('综合最大值',target_width)
//值范围大小限制
if (target_width > option.max) {
target_width = option.max
} else if(target_width < option.min){
target_width = option.min
}
console.log('列宽最终值',title,target_width)
//返回结果
return target_width
//计算字符串的占位宽度
function getTextWidth(str = '') {
//如果参数是字符串或者数字,则表示占位宽度已经计算
if(typeof str == 'string' || typeof str == 'number' ){
const dom = document.createElement('span')
dom.style.display = 'inline-block'
dom.style['font-size'] = option.font_size + 'px'
dom.textContent = str
document.body.appendChild(dom)
//额外多加5像素,防止误差
const width = dom.clientWidth + 5
document.body.removeChild(dom)
return width;
}else{
//如果不是这两类,无论是布尔类型,对象,数组都是不可测量占位宽度 直接返回最小值
return option.min
}
}
//计算字符串数组中的最大宽度
function getMaxWidthByArray(text_arr = []) {
//计算设备编号占位的最大宽度
var max_width = 0
text_arr.forEach(function (str) {
var now_text_width = getTextWidth(str)
if (now_text_width > max_width) {
max_width = now_text_width
}
})
return max_width
}
})
}
}
}))
<el-table :data="tableData" style="width: 100%" size="small" border>
<el-table-column prop="program_name" label="程序名称" :width="tableData | maxWidthForColumn('program_name','程序名称')">
</el-table-column>
</el-table>
参数 |
默认值 |
说明 |
参数一 |
空字符串 |
列字段名 |
参数二 |
空字符串 |
列标题 |
参数三 |
{} |
配置项,字体大小,padding等 |
参数 |
默认值 |
说明 |
font_size |
12 |
字体大小 |
padding |
10 |
padding大小 |
max |
300 |
最大值 |
min |
80 |
最小值 |
diy_render |
false |
如果此列开启了自定义渲染,请置为true,之后不再计算其字符串占位宽度 |
3.表格样式调整
- 表格有默认的边框颜色,背景色,字体颜色,某些需求下需要进行替换(例如看板)
/* 边框颜色重置 */
.table-box .el-table,
.table-box .el-table__header,
.table-box .el-table__body,
.table-box .el-table th,
.table-box .el-table td{
border-color: #223F96;
}
.table-box .el-table::before,
.table-box .el-table--border::after{
background-color:#223F96;
}
/* 背景色重置 */
.table-box .el-table,
.table-box .el-table th, .table-box .el-table tr{
background-color: transparent;
}
/* 字体颜色重置 */
.table-box .el-table,
.table-box .el-table thead,
.table-box .el-table__empty-text{
color:rgba(255, 255, 255, 0.75);
}
/* 斑马样式重置 */
.table-box .el-table--striped .el-table__body tr.el-table__row--striped td{
background-color: rgba(255, 255, 255, 0.03);
}
/* hover样式重置 */
.table-box .el-table--enable-row-hover .el-table__body tr:hover>td{
background-color: rgba(255, 255, 255, 0.05);
}
/* 表头下边框 */
.el-table th.el-table__cell.is-leaf {
border-bottom: 1px solid #223F96;
}
4.表格布局异常
- 当配合tab切换渲染具有固定高度的表格时,会导致表格布局异常(原因:表格渲染过程中,容器处于隐藏状态,会导致这种情况发生)
- 当进行tab切换时,会刷新所在容器的组件布局,所以默认选中的tab中的表格会高度异常,其他的就不会
- 为了保证默认tab中的表格布局正常,需要对tab进行手动切换,分三步走:
- 1.取消tab默认选中
- 2.监听第一个表格的渲染完成事件
- 3.表格的渲染完成事件后选中tab,触发布局刷新
<el-tabs v-model="active_tab" type="border-card">
<el-tab-pane label="角色平板权限" name="first">
<!-- 角色平板权限组件 -->
<pad-authority @mounted="padTableMounted"></pad-authority>
</el-tab-pane>
<el-tab-pane label="角色工位权限" name="second">
<!-- 角色工位权限组件 -->
<step-authority></step-authority>
</el-tab-pane>
<el-tab-pane label="角色功能权限" name="third">
<opration-authority></opration-authority>
</el-tab-pane>
</el-tabs>
data(){
return {
active_tab: "",//当前激活的tab
},
components:{
"pad-authority": httpVueLoader('/components/pad-authority.vue?time='+new Date().getTime()),//角色平板权限组件
"step-authority": httpVueLoader('/components/step-authority.vue?time='+new Date().getTime()),//角色工位权限组件
"opration-authority": httpVueLoader('/components/opration-authority.vue?time='+new Date().getTime()),//角色功能权限组件
},
methods:{
//角色平板权限组件的表格渲染完成事件
//未激活的tab内容区高度为0 此时渲染有固定高度的表格会导致高度异常
//但是tab切换显示时会自动刷新所在tab内容区的表格布局,利用这一点,等待表格渲染结束后,可以自动切换tab,从而避免表格高度异常
padTableMounted(){
setTimeout(()=>{
this.active_tab = 'first'
},10)
}
}
},
<el-table v-if="initHeight">< el-table>
//高度计算就绪
this.initHeight = true
this.$nextTick(function(){
//pad表格渲染完毕 通知父组件
this.$emit('mounted')
})