element踩坑记录

1,391 阅读3分钟

Plus版本

element-plus@2.0.4

el-table自定义行合并单元格

思路 第一步:是通过reduce方法对数组进行重新排序,合并相同类型数据, 第二步:设置rowspan和colspan,逻辑是给相同类型数组第一个元素赋值整个数组的长度,其他元素赋值0 第三步:通过concat合并数组

const groupBy = (objectArray, property) => {
  let groupedArr = objectArray.reduce(function (acc, obj) {
    let key = obj[property]
    if (!acc[key]) {
      acc[key] = []
    }
    acc[key].push(obj)
    return acc
  }, {})

  let formatArr = []
  for(let i in groupedArr) {
    console.log(i, groupedArr[i])
    groupedArr[i].map((item,index) => {
      index === 0 ? item.$rows = groupedArr[i].length:
          item.$rows = 0;
    })
    formatArr = formatArr.concat(groupedArr[i])
  }

  return formatArr
}

第四步:设置span-method方法

const objectSpanMethod = (
    { row,
      column,
      rowIndex,
      columnIndex,
    }) => {
  if (columnIndex === 0) {
    return {
      rowspan: row.$rows,
      colspan: row.$rows ? 1 : 0,
    }
  }
}

el-progress

修改背景色

div.c-b-meter
  el-progress(:width="55"
    :stroke-width="3"
    :stroke="'#000000'"
    type="dashboard"
    :color="'#34FFCD'"
    :percentage="percentage" )
.c-b-meter
  width 84px
  height 72px
  background url("~@/assets/images/big/meter_1.png")
  background-size 100% 100%
  margin-bottom 6px
  display flex
  justify-content center
  align-items flex-end
  >>> .el-progress-circle__track
    stroke: rgba(255, 255, 255, 0) !important; // 地图修改成透明
  >>> .el-progress__text // 修改中间的字体
    display: block;
    color: #ffffff;
    font-family: DS-Digital;
    font-size: 18px !important;

原来的 image.png

实现效果 image.png

UI版本

element-ui@2.12.0

滚动条组件

官网上并没有暴露出来这个组件,通过el-scrollbar包裹想要滚动的组件,然后在css样式文件里面,添加样式就可以了

首先,el-scrollbar组件的父级一定要有高度,其次el-scrollbar__thumb这个样式是设置滚动条的,不添加就没有滚动条了

未开放的滚动条组件

html

<el-scrollbar class="scroll-class">
	<div class="filter-tree"></div>
</el-scrollbar>

css

.scroll-class
  height 100%
  .filter-tree
    span
      font-size 16px
  .el-scrollbar__thumb
    height: 5%;

文档

table组件

取消表格hover变色

设置表格样式tr

tr
  pointer-events: none;

设置单元格合并

主要是span-method函数,data数据就按官网的来

el-table(:data="tableData"
        :span-method="objectSpanMethod"
        style="width: 100%")
 /**
     * 合并单元表格
     * @param row 当前行内容
     * @param column 当前列内容
     * @param rowIndex 当前行号
     * @param columnIndex 当前列号
     * @returns {{colspan: number, rowspan: *}|{colspan: number, rowspan: number}}
     */
    objectSpanMethod({ row, column, rowIndex, columnIndex }) {
      if (columnIndex === 0 || columnIndex === 5 || columnIndex === 6) { // 用于设置要合并的列
        if (rowIndex === 0) { // 用于设置合并开始的行号
          return {
            rowspan: this.tableData.length,  // 合并的行数
            colspan: 1 // 合并的列数,设为0则直接不显示
          };
        } else { // 返回不合并数据
          return {
            rowspan: 0,
            colspan: 0
          };
        }
      }
    }

自适应高度和滚动条

设定两个属性一个是max-height,用来确定自适应高度,height用来固定表头,增加滚动条

<div ref="userBox" v-if="flag">
    <el-table border
                  :height="tableHeight"
                  :max-height="tableHeight"
                  style="width: 100%">
    </el-table>
</div>    

如果是在v-if控制的组件中,这需要通过this.$nextTick(() => {})来控制

通过v-if加载的组件,一开始是无法通过this.$ref来获取dom元素的,所以要用到$nextTick函数

$nextTick

$nextTick 是在下次 DOM 更新循环结束之后执行延迟回调,在修改数据之后使用 $nextTick,则可以在回调中获取更新后的 DOM

所以$nextTick函数在vue中的的作用是当数据更新了,在dom中渲染后,自动执行该函数

this.$nextTick(() => {
    // v-if控制的组件userBox,通过ref拿到dom,然后设置表格的高度为dom 的50%
    // 一定要加'PX',否则table组件识别不了高度
    this.tableHeight = (this.$refs.userBox.offsetHeight * 0.5).toFixed(1) + 'px'
})

调整table标题颜色

<el-table :header-cell-style="{background:'#eef1f6',color:'#606266'}">
</ el-table>

调整table数据行高和字体

<el-table :cell-style="{font-size: '14px',padding:'7px'}">
</el-table>

自增id

  1. 普通
el-table(:data="tableData" style="width: 100%" height="100%" :header-cell-style="{color:'#354559'}")
        el-table-column(label="序号"
            type="index"
            width="50")
        el-table-column(v-for="(item, index) in tableTitle"
                        :key="index"
                        :prop="item.value"
                        :show-overflow-tooltip="true"
                        :label="item.text")
  1. 分页
el-table(:data="tableData" style="width: 100%" height="100%" :header-cell-style="{color:'#354559'}")
        el-table-column(label="序号"
            type="index"
            :index="indexMethod"
            width="50")
        el-table-column(v-for="(item, index) in tableTitle"
                        :key="index"
                        :prop="item.value"
                        :show-overflow-tooltip="true"
                        :label="item.text")
// 分页序号, currentPage是分页的页数,pageSizes是一页的数据量
indexMethod (index) {
  return (index + 1) + (this.currentPage - 1) * (this.pageSizes)
}

分页组件

el-pagination.pagination-class(background
                              layout="total, prev, pager, next"
                              @current-change="handleCurrentChange"
                              :page-size="pageSizes"
                              :current-page.sync="currentPage"
                              :total="totalSize")
属性说明可选值默认值
background是否为分页按钮添加背景色-false
layout组件布局,子组件名用逗号分隔sizes, prev, pager, next, jumper, ->, total, slot'prev, pager, next, jumper, ->, total'
total总条目数--
current-page当前页数,支持 .sync 修饰符-1
page-size每页显示条目个数,支持 .sync 修饰符-10

事件说明回调参数
current-changecurrentPage 改变时会触发当前页

时间选择器组件

设置选择时间小于当前时间

el-date-picker(v-model="valueStart"
                        type="month"
                        :picker-options="pickerOptions"
                        placeholder="选择月份")

在data里增加属性

pickerOptions: {
    disabledDate(date) {
      return date.getTime() > Date.now();
    }
},

设定初始化时间,单个选择框

el-date-picker(v-model="valueStart"
                        type="month"
                        placeholder="选择月份")

在data里面设置初始值,并在mounted周期赋值

data () {
    return {
        valueStart: ''
    }
}
mounted() {
    this.valueStart = new Date().toDateString()
}

设定初始化时间,两个选框

data () {
    return {
        valueStart: []
    }
}
mounted() {
    this.valueStart = [new Date().toDateString(), new Date().toDateString()]
}

格式化时间

通过watch监听数据

watch: {
    valueStart: {
      handler (newValue, oldValue) {
        // 精确到秒
        let time1 = new Date(newValue.toString())
        // this.sTime = time1.getFullYear() + '-' + formatTime(time1.getMonth() + 1)  + '-' + formatTime(time1.getDate()) + ' ' + formatTime(time1.getHours())  + ':' + formatTime(time1.getMinutes()) + ':' + formatTime(time1.getSeconds())
        this.sTime = time1.getFullYear() + '-' + formatTime(time1.getMonth() + 1)
      },
      deep: true
    },
}

函数用于小于10则补0

// 格式化时间
export const formatTime = (time) => {
  if (Number(time) < 10) {
    time = '0' + time
  }
  return time
}

tree 组件

点箭头图标的时候才会展开或者收缩节点

设置 expand-on-click-node

el-tree(ref="treeRef"
        :expand-on-click-node="false")

属性为false

默认展开

设置default-expand-all属性,默认值为true

el-tree(:data="treeData"
        default-expand-all
        :props="defaultProps")
data () {
    return {
        treeData: [{
          label: '一级 1',
          children: [{
            label: '二级 1-1',
            children: [{
              label: '三级 1-1-1'
            }]
          }]
        }],
        expandAll: true,
        defaultProps: {
            children: 'children',
            label: 'label'
         },
    }
}

自定义tree数据字段

treeData里面的字段要和defaultProps里面对上

data () {
    return {
        treeData: [{
          name: '一级 1',
          child: [{
            name: '二级 1-1',
            child: [{
              name: '三级 1-1-1'
            }]
          }]
        }],
        expandAll: true,
        defaultProps: {
            children: 'child',
            label: 'name'
         },
    }
}

设置筛选框,并增加输入未搜索到时,收起tree

增加input标签

 el-input(placeholder="输入关键字进行过滤"
                    v-model="filterText")

filter-node-method属性,返回一个函数,用来过滤

el-tree(:data="treeData"
                ref="tree"
                :default-expand-all="expandAll"
                :filter-node-method="filterNode"
                :props="defaultProps")

collapseAll函数是用来收起tree

methods() {
     /**
     * 筛选节点
     */
    filterNode(value, data) {
      if (!value) {
        this.collapseAll()
        // this.$refs.tree.store.defaultExpandAll = true
        // this.expandAll = false
      }
      return data.menuName.indexOf(value) !== -1;
    },
  
    // 全部折叠
    collapseAll () {
      this.expandAll = false;
      for(let i=0; i < this.$refs.tree.store._getAllNodes().length ; i++) {
        this.$refs.tree.store._getAllNodes()[i].expanded = this.expandAll;
      }
    },
}

复选框设置初始值

  1. node-key一定要是数据里面的唯一值
  2. default-checked-keys为数组,里面填的是node-key指定的字段
el-tree(:data="treeData"
        :default-expand-all="expandAll"
        node-key="id"
        show-checkbox
        :default-checked-keys="idArr"
        :props="defaultProps")
data () {
    return {
        treeData: [{
          id: 1,
          label: '一级 1',
          children: [{
            id:1-1,
            label: '二级 1-1',
            children: [{
              id:1-1-1,
              label: '三级 1-1-1'
            }]
          }]
        }],
        defaultProps: {
            children: 'children',
            label: 'label'
         },
        idArr: [1]
    }
}

设置不满足条件时,复选框不选中

el-tree(:data="treeData"
        show-checkbox
        ref="tree"
        @check="handleCheck"
        :props="defaultProps")
/**
     * 选择节点
     * @param data
     */
    handleCheck(e, a) {
      console.log('一个', e, a);
      // a.checkedKeys 为当前选择的节点格式为[1,2,3]
      // 点击的是时候,根据a.checkedKeys,做一个判断,如果不满足条件,则把加入的这一项从a.checkedKeys中剔除
      a.checkedKeys.map((item, index) => {
        if (条件) {
            alert('未满足条件,不能选')
            a.checkedKeys.splice(index, 1)
        }
      })
      
      // 按当前路径赋值到tree组件
      this.$refs.tree.setCheckedKeys(a.checkedKeys)
    },

获取半选的节点

属性说明
default-checked-keys默认值[1,2,3], 数组内放node-key确定的唯一id

方法说明参数
getHalfCheckedKeys若节点可被选择(即 show-checkbox 为 true),则返回目前半选中的节点的 key 所组成的数组
getCheckedKeys若节点可被选择(即 show-checkbox 为 true),则返回目前被选中的节点的 key 所组成的数组
<el-tree ref="menuTree"
                   :data="treeMenu"
                   show-checkbox
                   node-key="menuId"
                   default-expand-all
                   @check="showNode"
                   :props="defaultProps"
                   :default-checked-keys="drawerKeys" ></el-tree>

当用户没有选择,则有默认值,默认值可以通过以下方法来确认当前节点和半选节点的数据 this.$refs.menuTree.getCheckedKeys().concat(this.$refs.menuTree.getHalfCheckedKeys())

当前用户手动触发后,则通过改方法获取当前的节点

 showNode(e, node) {
      // console.log('eee', node.checkedKeys)
      // this.cacheChecked = node.checkedKeys
      // 选择半选和全选的节点
      this.cacheChecked = this.$refs.menuTree.getCheckedKeys().concat(this.$refs.menuTree.getHalfCheckedKeys())
      console.log('eee', this.cacheChecked)
    }

全选/反选

<div align="right">
       <el-checkbox v-model="checked" @change="checkedAll"/> 全选/反选
</div>
<el-tree :data="treeMenu" ref="vuetree" show-checkbox :default-checked-keys="checkedKeys" :props="defaultProps">
</el-tree>
treeMenu: [],  //存放树形组件的data
checked:false, //checkbox的值
checkedAll(){
        if (this.checked) {
            //全选
            this.$refs.vuetree.setCheckedNodes(this.treeMenu);
        }else{
            //取消选中
            this.$refs.vuetree.setCheckedNodes([]);
        }
},

loading组件

区域加载

通过v-loading指令

div(v-loading="loading")

loading为true则显示loading

data () {
    return {
        loading: false
    }
}

整页加载

设置

import { Loading } from 'element-ui';

export const elementLoading = async (msg) => {
  return new Promise((resolve, reject) => {
    resolve(Loading.service({text: msg}))
  })
};

export const elementHideLoading = async () => {
  return new Promise((resolve, reject) => {
    resolve(Loading.service().close())
  })
};

调用

import { elementHideLoading, elementLoading } from "../../utils/elementApi";
elementLoading('编辑中') // 展示loading
elementHideLoading() // 取消展示

遮罩层出现在弹出层外面