Element-UI 各类使用记录,报错集合,需求解决(持续更新--3月4更新)

618 阅读11分钟

循序渐进,从无到有,由浅入深

2025年3月4日更新

15.el-tree 节点树再次请求数据后会自动折叠,解决方案

首先出问题的源头就是它又重新请求节点树数据了,所以导致节点树刷新并折叠。

image.png :default-expanded-keys="expaAndList" // expaAndList 是一个数组 在data中定义。

解决方案如下:

  • 添加这里 node-key='treeId' :default-expanded-keys="expaAndList"
  • 点击时,将id传入既可
<template>
  <div>
  
     <!-- 添加这里  node-key='treeId'
      :default-expanded-keys="expaAndList" -->
    <el-tree 
      style="width: 200px; border: 1px solid red; margin: 10px auto"
      :data="data" 
      :props="defaultProps"
      node-key='treeId'
      :default-expanded-keys="expaAndList"
      @node-click="handleNodeClick">
    </el-tree>
    <button @click="submit">提交</button>
  </div>
</template>
 
<script>
import axios from 'axios'
export default {
  data() {
    return {
      data:[],
      expaAndList:[],
      defaultProps: {
        label:"names",
        children:"ch"
      }
    }
  },
 
  created() {
    this.getTreeList()
  },
 
  methods: {
  //节点点的事件
    handleNodeClick(data) {
    //将当前节点的id传入数组既可
      this.expaAndList = data.treeId
    },
    submit() {
      setTimeout(() => {
        this.getTreeList()
      }, 1000) // 点击提交请求接口 这里用setTimeout模仿
    },
    getTreeList() {
      axios({
        url:"http://localhost:8080/tree.json"
      }).then(res => {
        // console.log(res);
        this.data = Object.freeze(Object.assign([], res.data.data))
        console.log(this.data);
      })
    }
  }
}
</script>

2025年2月20日更新

14.Vue2 + ElementUI拖动侧边栏以便自由调整左右两侧的宽度

要实现的效果如下: project9.gif 完整可实现代码如下:可以直接复制

<template>
  <el-row class="contnet" :gutter="20">
    <!-- // 1. 左侧树 -->
    <el-col id="left-tree" class="left-tree" :offset="0" :span="6">
      <el-tree :data="data" show-checkbox node-key="id" :default-expanded-keys="[2, 3]" :default-checked-keys="[5]" :props="defaultProps">
      </el-tree>
      <!-- // 2. 中间拖动栏 -->
      <div id="resize" class="resize" title="收缩侧边栏"></div>
    </el-col>
    <!-- // 3. 右侧内容 -->
    <el-col id="right-content" class="right-content" :offset="0" :span="18">
      <el-table ref="table" border :data="list" row-key="id" style="width: 100%">
        <el-table-column type="selection" width="55" />
        <el-table-column align="center" label="#" width="55">
          <template #default="{ $index }">
            {{ $index + 1 }}
          </template>
        </el-table-column>
        <el-table-column label="文件名称" prop="originalName" />
      </el-table>
    </el-col>
  </el-row>
</template>

<script>
export default {
  components: {},
  data() {
    return {
      list: [],
      data: [
        {
          id: 1,
          label: "一级 1",
          children: [
            {
              id: 4,
              label: "二级 1-1",
              children: [
                {
                  id: 9,
                  label: "三级 1-1-1",
                },
                {
                  id: 10,
                  label: "三级 1-1-2",
                },
              ],
            },
          ],
        },
        {
          id: 2,
          label: "一级 2",
          children: [
            {
              id: 5,
              label: "二级 2-1",
            },
            {
              id: 6,
              label: "二级 2-2",
            },
          ],
        },
        {
          id: 3,
          label: "一级 3",
          children: [
            {
              id: 7,
              label: "二级 3-1",
            },
            {
              id: 8,
              label: "二级 3-2",
            },
          ],
        },
      ],
      defaultProps: {
        children: "children",
        label: "label",
      },
    };
  },
  mounted() {
    this.dragControllerDiv();
  },
  methods: {
    dragControllerDiv() {
      // 获取左侧树形结构的DOM元素
      const left = document.getElementById("left-tree");
      // 获取用于调整大小的线条的DOM元素
      const line = document.getElementById("resize");
      // 获取右侧内容区域的DOM元素
      const right = document.getElementById("right-content");

      // 为调整大小的线条添加鼠标按下事件监听器
      line.onmousedown = (e) => {
        // 记录鼠标按下时的X坐标
        const startX = e.clientX;
        // 记录线条初始的left偏移量
        const initialLeft = line.offsetLeft;

        // 定义鼠标拖动事件的处理函数
        const onMouseMove = (e) => {
          // 计算线条新的left偏移量
          const moveLen = initialLeft + (e.clientX - startX);
          // 计算最小宽度(视口宽度的10%)
          const minWidth = document.body.clientWidth * 0.1;
          // 计算最大宽度(视口宽度的40%)
          const maxWidth = document.body.clientWidth * 0.4;

          // 检查新的left偏移量是否在允许的范围内
          if (moveLen >= minWidth && moveLen <= maxWidth) {
            // 设置线条新的left偏移量
            line.style.left = moveLen + "px";
            // 设置左侧树形结构新的宽度
            left.style.width = moveLen + "px";
            // 设置右侧内容区域新的宽度,确保左右两侧总宽度等于视口宽度
            right.style.width = document.body.clientWidth - moveLen + "px";
          }
        };

        // 定义鼠标抬起事件的处理函数
        const onMouseUp = () => {
          // 移除鼠标拖动事件监听器
          document.removeEventListener("mousemove", onMouseMove);
          // 移除鼠标抬起事件监听器
          document.removeEventListener("mouseup", onMouseUp);
        };

        // 添加鼠标拖动事件监听器
        document.addEventListener("mousemove", onMouseMove);
        // 添加鼠标抬起事件监听器
        document.addEventListener("mouseup", onMouseUp);
      };
    },
  },
};
</script>

<style lang="scss" scoped>
.contnet {
  display: flex; /* 使用flex布局,使子元素可以按照弹性盒子模型排列 */
}

.left-tree {
  position: relative; /* 相对定位,使内部的绝对定位元素(如.resize)相对于此元素定位 */
  width: 500px; /* 左侧树形结构的宽度为500像素 */
  height: 100%; /* 高度占满父元素的100%,如果存在box-sizing,此处设置会影响,可以先去掉看看效果 */
  background: #fff; /* 背景颜色为白色 */
  box-shadow: 0 0 2px 2px rgba(0, 0, 0, 0.050980392156862744); /* 添加轻微的阴影效果 */
  border-radius: 4px; /* 边框圆角为4像素 */
  vertical-align: top; /* 垂直方向上与相邻行内元素顶部对齐 */
  display: inline-block; /* 显示为行内块元素 */
  box-sizing: border-box; /* 盒模型采用border-box,这样padding和border不会增加元素的宽度和高度 */
  -ms-flex-negative: 0; /* 兼容性设置,阻止在IE 10及以下版本中收缩 */
  flex-shrink: 0; /* 阻止收缩,确保左侧树形结构在父容器中不被压缩 */
  padding: 10px 0 0 10px; /* 内边距设置,上0,右0,下0,左10像素 */
  margin-right: 8px; /* 右侧外边距为8像素 */
}

.resize {
  cursor: col-resize; /* 鼠标悬停时显示列调整的光标 */
  position: absolute; /* 绝对定位,相对于最近的已定位祖先元素进行定位 */
  top: 45%; /* 距离顶部50%,垂直居中 */
  right: -8px; /* 距离右侧-8像素,显示在左侧树形结构的右侧边缘 */
  background-color: #d6d6d6; /* 背景颜色为浅灰色 */
  border-radius: 5px; /* 边框圆角为5像素 */
  margin-top: -10px; /* 上方外边距为-10像素,调整垂直位置 */
  width: 10px; /* 宽度为10像素 */
  height: 50px; /* 高度为50像素 */
  background-size: cover; /* 背景图片覆盖整个元素 */
  background-position: 50%; /* 背景图片居中显示 */
  font-size: 32px; /* 字体大小为32像素 */
  color: #fff; /* 字体颜色为白色 */
}

.right-content {
  display: inline-block; /* 显示为行内块元素 */
  width: calc(
    100% - 510px
  ); /* 宽度为父元素宽度减去左侧树形结构宽度和调整边距,这里假设左侧树形结构宽度500px,右侧外边距8px,左侧内边距10px */
  height: 100%; /* 高度占满父元素的100% */
  background: #fff; /* 背景颜色为白色 */
  -webkit-box-shadow: 0 0 2px 2px rgba(0, 0, 0, 0.050980392156862744); /* 添加轻微的阴影效果,兼容webkit内核浏览器 */
  box-shadow: 0 0 2px 2px rgba(0, 0, 0, 0.050980392156862744); /* 添加轻微的阴影效果 */
  border-radius: 4px; /* 边框圆角为4像素 */
  -webkit-box-sizing: border-box; /* 兼容性设置,盒模型采用border-box */
  box-sizing: border-box; /* 盒模型采用border-box,这样padding和border不会增加元素的宽度和高度 */
  padding: 10px; /* 上下左右内边距均为10像素 */
  vertical-align: top; /* 垂直方向上与相邻行内元素顶部对齐 */
  overflow: auto; /* 内容超出容器时出现滚动条 */
}
</style>

阐述:

(1).content{ display:flex;} 一定要有,否则在拖拽时会出现换行的情况 (2)resize 要相对于父级绝对定位 去掉el-table 底部边框

 .el-table::before {
    height: 0px;
  }

box-sizing盒模型

  • (1)content-box 标准盒模型
  • (2)border-box 怪异盒模型

2025年2月19日更新

13. el-date-picker 添加时间后者不可小于前者

image.png

代码如下:

 <div>
            <el-date-picker size="mini" v-model="queryfrom.ApplyStartDate" type="date" placeholder="开始日期" style="width:130px" value-format="yyyy-MM-dd" @change="timeChange" />--
            <el-date-picker size="mini" v-model="queryfrom.ApplyEndDate" type="date" placeholder="结束日期" style="width:130px" value-format="yyyy-MM-dd" @change="timeChange" :picker-options="pickerOptions" />&nbsp;&nbsp;
          </div>

解释如下:

image.png

 data() {
  let that = this
    return {
      pickerOptions: {
        disabledDate(time) {
          return time.getTime() < new Date(that.queryfrom.ApplyStartDate).getTime() // 小于指定时间都不可选
        },
      },
 }

2025年2月12日更新

12. el-tree的宽不够了,导致文本超出

问题描述:el-tree展开子节点后宽度没有撑开,溢出内容隐藏了,不显示横向滚动条。 image.png 需要出现横向的滚动条,elment-ui官方的issue

# 关于tree里面overflow的问题

  • 给el-tree的父元素加上 overflow: auto;没用,

  • 解决方法,加样式

<style scoped>
::v-deep .el-tree-node.is-expanded > .el-tree-node__children {
  display: inline;
}
</style>

2025年2月10日更新

11. el-table 实现点击任何一处展开行功能

正常默认是点击行前面的向右箭头展开行,需求是点击整行的任何一处,即可展开。效果如下: project9.gif 实现也不是不可能,table组件提供很过的API和属性,通过组合即可实现。先设置行的 row-key 属性,然后利用 expand-row-keys 属性来控制当前展开的行,它是一个数组,可控制多行展开。最后通过 row-click 事件API来触发更新 expand-row-keys 数组。

代码如下:

<el-table
    :row-key="(row) => { return row.id }"
    :expand-row-keys="expands"
    @row-click="clickRowHandle">
</el-table>

data() {
    return {   
      expands: [],
  },

methods: {
    clickRowHandle(row, column, event) {
        if (this.expands.includes(row.id)) {
             this.expands = this.expands.filter(val => val !== row.id);
        } else {
             this.expands.push(row.id);
        }
    }
}

2025年2月5更新

开工大吉

52e778435d3af63c3d3ae61a6c1267d.png

10. 整合之前的笔记记录

  1. 设置el-dialog里面的内容滚动
  2. el-table设置纵向滚动
  3. 如何监听当前行的数据有变化时,才..
  4. input 各个事件
  5. 数组的map方法
  6. 页面切换时window.scrollTop(0,0)...
  7. computed 传参
  8. el-table修改表头和表格的背景颜色
  9. 通过插槽修改el-table的表头样式

以上记录直达地址

9. 其他记录地址如下:

工作中element-ui的使用记录(一)多选,单选,动态表格,下拉框,表单验证,时间限制,级联选择器处理,el-input只输入数字

很久之前的实习笔记记录库如下-顺带合在一起了

  1. element-ui表格列el-table-column...
  • 方法一、格式化数据
  • 方法二:直接在template scope 使... 获取element-ui表格中的渲染的prop...
  1. el-select获取选中的 label跟 value
  2. 修改element-ui组件的样式

2025年1月21更新

8. el-checkbox的 indeterminate 属性的作用

在elementUI官网中是这么解释的:设置 indeterminate 状态,只负责样式控制 。

它配合 v-model ="checkAll"使用,改变的是“全选”前面的那个框的样式

indeterminate 表示的是多选框的一种不确定状态,

  • true 表示:既不是全选,也不是全不选,代表了一种不确定的状态
  • false 表示:要么是全选,要么是全不选,代表了一种确定的状态

那么,indeterminate 和 checkAll 是如何决定 “全选” 前面那个框的样式的?

举个例子:

indeterminatecheckAll样式
truetrue-
truefalse-
falsetrue
falsefalse

状态一二的效果如下:

image.png

状态三如下:

image.png

状态四:默认如下:

image.png

2025年1月14日更新

7. el-tree 解决勾选会把父节点下的子节点全部勾选的问题

工作遇到新需求如下: project9.gif

  1. 点击勾选时,父节点以及祖先节点全部选中

  2. 子级取消选中,父级选中效果不变

关于Vue  tree组件 动态渲染编辑时 选择父级时会全选所有的子级(el-tree数据回显父节点和子节点都会被选中)

  1. 解决方法一
  • check-strictly属性

image.png

但是这样会出现一个问题,当前节点选中,但是父级没有联动选中。

  1. 解决方法二(推荐)
  • 思路:自定义勾选后实现的效果,选中时,则一并选中该节点的子节点与父节点,取消时,则一并取消子节点,但不处理父节点。

el-tree部分:

  • check-strictly = true , 切断父级与子级之间的关系

  • check = "handleCheck" , 自定义勾选效果

methods部分:

  • handleCheck, 自定义勾选效果方法,实现上文所说的两点需求

完整可实现代码如下

<template>
  <div class="BatchMove">

    <el-tree :data="data" show-checkbox node-key="DirectoryId" default-expand-all :expand-on-click-node="false" :props="defaultProps" @check="handleCheck" ref="tree" :check-strictly="true">
      <span class="custom-tree-node" slot-scope="{ node, data }">
        <span>{{ node.label }}</span>
        <span>
          <el-button type="text" size="mini" @click="moveHandle(node, data)" :disabled="data.ParentDirIdTag === 0">
            移动
          </el-button>

        </span>
      </span>
    </el-tree>
  </div>
</template>
<script>
// batchMoveApi
import { batchMoveApi } from '@/api/front/fileMessage.js'
export default {
  name: 'BatchMove',
  props: {
    treeData: {
      type: Array,
      default: () => [],
    },
    multipleSelection: {
      type: Array,
      default: () => [],
    },
  },
  data() {
    return {
      defaultProps: {
        children: 'children',
        label: 'DirectoryName',
        disabled: function (data, node) {
          //带子级的节点不能选中

          if (data.ParentDirIdTag === 0) {
            return true
          } else {
            return false
          }
        },
      },
      data: JSON.parse(JSON.stringify(this.treeData)),
    }
  },
  components: {},
  computed: {},
  methods: {
    /**
     * 处理节点选中状态变化
     * @param {Object} data - 当前节点的数据
     * @param {Object} nodeInfo - 包含选中节点信息的对象
     */
    handleCheck(data, nodeInfo) {
      const { checkedKeys } = nodeInfo

      // 获取当前操作的节点实例
      const currentNode = this.$refs.tree.getNode(data.DirectoryId)
      console.log('currentNode', currentNode)
      // DirectoryId 这个id是树节点的唯一id,用来标识节点,替换成你自己的id
      if (checkedKeys.includes(data.DirectoryId)) {
        // 节点被选中时:
        // 1. 先取消选中状态(防止子节点自动选中)
        this.$refs.tree.setChecked(data.DirectoryId, false)
        // 2. 重新选中当前节点
        this.$refs.tree.setChecked(data.DirectoryId, true)
        // 3. 选中所有父节点
        this.selectParentNodes(currentNode)
      } else {
        // 节点取消选中时:取消所有子节点的选中状态
        this.unselectChildNodes(currentNode)
      }
    },

    /**
     * 递归取消所有子节点的选中状态
     * @param {Object} node - 当前节点实例
     */
    unselectChildNodes(node) {
      // 如果存在子节点,则递归处理
      if (node.data.children && node.data.children.length > 0) {
        node.data.children.forEach((child) => {
          // 取消当前子节点的选中状态
          this.$refs.tree.setChecked(child.DirectoryId, false)
          // 获取子节点实例
          const childNode = this.$refs.tree.getNode(child.DirectoryId)
          // 递归处理子节点的子节点
          this.unselectChildNodes(childNode)
        })
      }
    },

    /**
     * 递归选中所有父节点
     * @param {Object} node - 当前节点实例
     */
    selectParentNodes(node) {
      // 如果存在父节点且不是根节点(DirectoryId !== 0),则继续处理
      if (node.parent && node.parent.data.DirectoryId !== 0) {
        // 选中父节点
        this.$refs.tree.setChecked(node.parent.data.DirectoryId, true)
        // 递归处理父节点的父节点
        this.selectParentNodes(node.parent)
      }
    },

    moveHandle(node, data) {
      console.log('multipleSelection', this.multipleSelection)
      let arr = this.multipleSelection.map((item) => item.FileMessageId)
      let obj = {
        DirectoryIdTag: node.data.DirectoryId,
        FileMessageIds: arr,
      }
      batchMoveApi(obj).then((res) => {
        console.log('res', res)
        this.$layer.msgSuccess(res)
        this.$parent.$parent.queryFiles()
        this.$parent.$parent.BatchMoveClick(false)
      })
      console.log('node', node)
    },
  },
  watch: {},
  mounted() {},
}
</script>
<style lang="scss" scoped>
.BatchMove {
  .custom-tree-node {
    flex: 1;
    display: flex;
    align-items: center;
    justify-content: space-between;
    font-size: 14px;
    padding-right: 8px;
  }
}
</style>

1. el-menu-item 使用时报错:Invalid prop: custom validator check failed for prop “index“.

报错信息只是指明了index有误,但是错误不够清晰 image.png

解决方法:将类型转化成字符串类型即可。

image.png

image.png

2. el-atble 列表 type="selection"设置默认选中

image.png 第一个参数是需要被勾选的行组成的列表,第二个参数为true,必须要传。

  showData() {
      this.tableData.forEach((el, index) => {
        if (this.articleContent.OperationTickSerials.includes(el.OperationTickSerial)) {
          this.$refs.multipleTable.toggleRowSelection(this.tableData[index], true)
        }
      })
    },

image.png

3. el-table 设置滚动加载

文档地址

1.安装插件el-table-infinite-scroll

npm install --save el-table-infinite-scroll

vue2的话是这个命令

npm install --save el-table-infinite-scroll@2
  1. 全局注册方法:在main.js文件中引入并全局注册
import Vue from 'vue';
import elTableInfiniteScroll from 'el-table-infinite-scroll';

Vue.use(elTableInfiniteScroll);

  1. 局部注册方法
<script>
import elTableInfiniteScroll from 'el-table-infinite-scroll';
export default {
  directives: {
    'el-table-infinite-scroll': elTableInfiniteScroll
  }
}
</script>

image.png

image.png

 // 上拉加载
    load() {
      console.log('queryform', this.queryform)
      this.queryform.PageIndex = this.queryform.PageIndex++
      this.queryform.PageSize = 10
      this.pullLoading = true
      getTicketTable(this.queryform).then((res) => {
        console.log('getTicket', res)
        this.tableData.push(...res.CurrentPageData)
        this.pullLoading = false
      })
     
    },

4.el-select下拉框设置默认值(赋值)失败

关于element select框默认值赋值不成功问题,注意两点:

  1. v-model里面的数据和遍历出来value值数据类型不一样。 (例:item.provinces类型是number,province类型是String。类型不一样导致赋值不成功)
  2. 遍历数据和赋值的先后顺序,必须保证数据先遍历后赋值。

image.png

要为select下拉框设定默认值,只需要把 v-model 绑定的值和你想要选中 option 的 value 值设置一样即可。

<el-select v-model="valuetype"  @change="changetype">
    <el-option v-for="item in options" :key="item.value" :label="item.label" :value="item.value">
    </el-option>
  1. table中的插槽使用

image.png

 <el-table-column width="120" property="ClassesName" label="班组">
                  <template v-slot:header>
                    <span v-if="[1, 2, 4, 5].includes(isPlain)">班组</span>
                    <span v-if="isPlain===3">排班数</span>
                  </template>
                </el-table-column>
                <el-table-column width="100" property="CMonthCount" label="已完成数" align="center">
                  <template v-slot:header>
                    <span v-if="[1, 2, 4].includes(isPlain)">已完成数</span>
                    <span v-if="isPlain===3">排班数</span>
                    <span v-if="isPlain===5">管控中数</span>
                  </template>

                  <template slot-scope="scope1">
                    <div>{{scope1.row.CMonthCount  }}</div>
                  </template>
                </el-table-column>

5. el-popover使用doclose关闭窗口不生效

  1. el-table表格中使用el-popover打开和关闭失效的问题及解决过程
    在 element-ui 中 el-table 中使用Popover弹框

image.png

  1. 这里ref使用变量的形式,因为是多个循环的el-popover*
    这里需要点击确定来关闭el-popover窗口,发现如下代码不生效

  2. 发现vue 不能检测到ref的值变化 不能触发视图更新,原因是表格中添加lazy 懒加载

通过如下代码解决

handleConfirm() {
 // 模拟点击页面其它部分关掉弹层,因为该页面列表使用懒加载导致doClose无效
	document.body.click()
}

image.png

6. el-tree 点击树的文字不要收缩仅点击图标的时候收缩

expand-on-click-node:是否在点击节点的时候展开或者收缩节点, 默认值为 true,如果为 false,则只有点箭头图标的时候才会展开或者收缩节点。

<el-tree
  :data="data"
  show-checkbox
  node-key="id"
  default-expand-all
  :expand-on-click-node="false"
  :render-content="renderContent">
</el-tree>