循序渐进,从无到有,由浅入深
2025年3月4日更新
15.el-tree 节点树再次请求数据后会自动折叠,解决方案
首先出问题的源头就是它又重新请求节点树数据了,所以导致节点树刷新并折叠。
: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拖动侧边栏以便自由调整左右两侧的宽度
要实现的效果如下:
完整可实现代码如下:可以直接复制
<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 添加时间后者不可小于前者
代码如下:
<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" />
</div>
解释如下:
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展开子节点后宽度没有撑开,溢出内容隐藏了,不显示横向滚动条。
需要出现横向的滚动条,elment-ui官方的issue
-
给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 实现点击任何一处展开行功能
正常默认是点击行前面的向右箭头展开行,需求是点击整行的任何一处,即可展开。效果如下:
实现也不是不可能,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更新
开工大吉
10. 整合之前的笔记记录
- 设置el-dialog里面的内容滚动
- el-table设置纵向滚动
- 如何监听当前行的数据有变化时,才..
- input 各个事件
- 数组的map方法
- 页面切换时window.scrollTop(0,0)...
- computed 传参
- el-table修改表头和表格的背景颜色
- 通过插槽修改el-table的表头样式
9. 其他记录地址如下:
工作中element-ui的使用记录(一)多选,单选,动态表格,下拉框,表单验证,时间限制,级联选择器处理,el-input只输入数字
- element-ui表格列el-table-column...
- 方法一、格式化数据
- 方法二:直接在template scope 使... 获取element-ui表格中的渲染的prop...
- el-select获取选中的 label跟 value
- 修改element-ui组件的样式
2025年1月21更新
8. el-checkbox的 indeterminate 属性的作用
在elementUI官网中是这么解释的:设置 indeterminate 状态,只负责样式控制 。
它配合 v-model ="checkAll"
使用,改变的是“全选”前面的那个框的样式
indeterminate 表示的是多选框的一种不确定状态,
- true 表示:既不是全选,也不是全不选,代表了一种不确定的状态
- false 表示:要么是全选,要么是全不选,代表了一种确定的状态
那么,indeterminate 和 checkAll 是如何决定 “全选” 前面那个框的样式的?
举个例子:
indeterminate | checkAll | 样式 |
---|---|---|
true | true | - |
true | false | - |
false | true | √ |
false | false | 无 |
状态一二的效果如下:
状态三如下:
状态四:默认如下:
2025年1月14日更新
7. el-tree 解决勾选会把父节点下的子节点全部勾选的问题
工作遇到新需求如下:
-
点击勾选时,父节点以及祖先节点全部选中
-
子级取消选中,父级选中效果不变
关于Vue tree组件 动态渲染编辑时 选择父级时会全选所有的子级(el-tree数据回显父节点和子节点都会被选中)
- 解决方法一
- check-strictly属性
但是这样会出现一个问题,当前节点选中,但是父级没有联动选中。
- 解决方法二(推荐)
- 思路:自定义勾选后实现的效果,选中时,则一并选中该节点的子节点与父节点,取消时,则一并取消子节点,但不处理父节点。
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有误,但是错误不够清晰
解决方法:将类型转化成字符串类型即可。
2. el-atble 列表 type="selection"设置默认选中
第一个参数是需要被勾选的行组成的列表,第二个参数为true,必须要传。
showData() {
this.tableData.forEach((el, index) => {
if (this.articleContent.OperationTickSerials.includes(el.OperationTickSerial)) {
this.$refs.multipleTable.toggleRowSelection(this.tableData[index], true)
}
})
},
3. el-table 设置滚动加载
1.安装插件el-table-infinite-scroll
npm install --save el-table-infinite-scroll
vue2的话是这个命令
npm install --save el-table-infinite-scroll@2
- 全局注册方法:在
main.js
文件中引入并全局注册
import Vue from 'vue';
import elTableInfiniteScroll from 'el-table-infinite-scroll';
Vue.use(elTableInfiniteScroll);
- 局部注册方法
<script>
import elTableInfiniteScroll from 'el-table-infinite-scroll';
export default {
directives: {
'el-table-infinite-scroll': elTableInfiniteScroll
}
}
</script>
// 上拉加载
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框默认值赋值不成功问题,注意两点:
v-model
里面的数据和遍历出来value值数据类型不一样。 (例:item.provinces
类型是number,province
类型是String。类型不一样导致赋值不成功)- 遍历数据和赋值的先后顺序,必须保证数据先遍历后赋值。
要为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>
- table中的插槽使用
<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关闭窗口不生效
- el-table表格中使用el-popover打开和关闭失效的问题及解决过程
在 element-ui 中 el-table 中使用Popover弹框
-
这里ref使用变量的形式,因为是多个循环的el-popover*
这里需要点击确定来关闭el-popover窗口,发现如下代码不生效 -
发现vue 不能检测到ref的值变化 不能触发视图更新,原因是表格中添加lazy 懒加载
通过如下代码解决
handleConfirm() {
// 模拟点击页面其它部分关掉弹层,因为该页面列表使用懒加载导致doClose无效
document.body.click()
}
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>