目录
- bug / 知识点
- 1.el-dialog打开后,页面布局发生偏移
- 2.el-table 错误复用之前的表格列,导致新表格内容展示错误
- 3.监听浏览器本地缓存的方法
- 4.通过 iframe 简单实现多系统快捷登录(类似单点登录效果,支持跨域)
- 5.VS Code代码提示突然没有了
- 6. 为什么通过ref获取到的组件,有时候是个对象,有时候是数组?(为什么通过ref获取到的组件,调用不了它里面的方法?)
- 7.为什么el-input-number 在人为清空后,用代码进行赋值会失效?(清空后赋值失效)
- 8. js 四舍五入方法实现
- 9. vue启动项目报错。defineConfig is not a function
- 10.flex:1 的宽度会被内容元素撑大
- 11.文字换行处理
- 12.echart 图表更新数据
- 13.扁平转树形
- 14.树形转扁平
bug / 知识点
1.el-dialog打开后,页面布局发生偏移
设置:lock-scroll=“false” 即可
<el-dialog
v-model="dialogVisible"
:title="dialogTitle"
:lock-scroll="false"
>
2.el-table 错误复用之前的表格列,导致新表格内容展示错误
情景: 今天发现个bug,界面右侧有三个表格,根据点击的位置不同,都做了v-if判断。根据点击的顺序不同,后点击展示的表格,会复用上一个已展示表格的列,导致表格某些列内容展示出错(主要是对上一个表格的操作列进行了复用,导致新展示的表格在同一个列索引的位置,出现操作按钮【本来该展示列绑定字段的内容】)
解决方法: 给 el-table-column 添加一个唯一 key,这样就能避免错误的复用,问题解决!
3.监听浏览器本地缓存的方法
mounted() {
window.addEventListener('storage', (e) => {
// e.key 为storage 里,你要监听的字段
if(e.key === 'xxxx') {
}
});
},
// 移除监听
beforeDestroy() {
window.removeEventListener("storage", () => {});
}
4.通过 iframe 简单实现多系统快捷登录(类似单点登录效果,支持跨域)
A系统地址: http://localhost:8080
B系统地址: http://localhost:8081
A 系统
// A 系统登录成功过后
// 获取 token
var token= res.data.token;
// 动态创建一个不可见的iframe,在iframe中加载一个跨域HTML
var iframe = document.createElement("iframe");
// iframe的src为B系统的地址
iframe.src = "http://" + window.location.hostname + ":8081";
document.body.append(iframe);
iframe.style.display = "none";
// 使用postMessage()方法将token传递给iframe
const href = "http://" + window.location.hostname + ":8081";
setTimeout(() => {
// 把登录成功后获取的token和用户名传递给B系统
iframe.contentWindow.postMessage({ systemToken: token, username: res.data.username }, href);
}, 2000);
setTimeout(function () {
// 销毁iframe
iframe.remove();
}, 6000);
B系统
// 接收A系统传递的token与用户名
window.addEventListener(
"message",
function (event) {
if (event.data && event.data.systemToken) {
if(localStorage.getItem("token") !== event.data.systemToken) {
localStorage.setItem("token", event.data.systemToken);
localStorage.setItem("username", event.data.username);
}
}
},
false
);
// 这里的监听是写在 App.vue 里的
// 同时,我们需要监听localStorage里的用户数据发生变化,让其回到登录页,选择最新的用户数据快速登录或手动登录
// A系统在传递的信息的时候,最后传递的是username。这里我们就监听username的变化
mounted() {
window.addEventListener('storage', (e) => {
if(e.key === 'username') {
this.$message({
type: 'warning',
message: '当前登录的账号已更新'
})
if(this.$route.name === 'Login') {
window.location.reload();
} else {
this.$router.replace({
name:'Login'
});
}
}
});
},
beforeDestroy() {
window.removeEventListener("storage", () => {});
}
5.VS Code代码提示突然没有了
在vue文件中,发现代码的提示突然没有了,找了下网上的方法,试了没有成功。然后我把编辑器以及所有的插件都重新安装了一遍,但依旧没有代码提示。
后面试了一个,稍有转机:
先在右下角把文件类型转为html,这个时候代码提示出来了
但再把文件类型选为自动检测,会自动转为.vue 文件。这个时候代码提示又没有了
(这个时候能够想到可能会跟.vue的什么有关联)
我的解决方法:
在这百思不得其解的情况下,我突然想起之前看到一个文章上说过
vetur 插件 与 Vue Language Features (Volar) 插件 不能同时使用
(都是支持vue的语法)
但因为之前编辑器里一直都有这两个插件,也没有什么影响,所以一直也没注意
最后把vetur插件卸载,只留一个Vue Language Features (Volar) 插件,重启编辑器过后,普天同庆!!!亲爱的代码提示终于又出来了!!!
6. 为什么通过ref获取到的组件,有时候是个对象,有时候是数组?(为什么通过ref获取到的组件,调用不了它里面的方法?)
-
原理:通过$refs获取到的组件,可以调用它自己组件里的方法。
-
问题发现:在通过$refs获取到的组件后,调用其方法无效,打印其方法为undefined
-
解决:这个时候,将获取到的组件进行打印,不难发现打印出来的是一个数组,还需要先通过下标获取到组件对象,就能成功调用。如图:
可是大多时候,我们拿着this.$refs[xxx].fn() 就能直接调用了,也就是大多时候通过 $ref 获取到的组件是一个组件对象,而不是一个组件对象的数组。
这里就是另一个问题:为什么通过ref获取到的组件有时候是个对象,有时候是数组???
总结:
- 在使用 ref 时,如果是直接定义的常量,通过 $ref 获取到的就是一个组件对象。如:
<echartDashboard
ref="dashboard"
>
</echartDashboard>
- 在使用 ref 时,如果是通过for循环实例出来的组件,ref 绑定的值是循环生成的,这个时候通过 $ref 获取到的就是一个组件对象数组。如:
<echartDashboard
v-for="(item, index) in detailData"
:key="item.devId"
:ref="`echart-dashboard-ref-${item.devId}`"
>
</echartDashboard>
7.为什么el-input-number 在人为清空后,用代码进行赋值会失效?(清空后赋值失效)
使用 $nextTick函数
el-input-number是element的一个组件,并非简单的标签,而change事件监听的是整个组件。
这里涉及到dom渲染与赋值的先后顺序,使用 $nextTick函数即可解决。
8. js 四舍五入方法实现
// 小数四舍五入转换
// number 值
// precision 保留的小数位
round(number, precision = 3) {
return Math.round(+number + 'e' + precision) / Math.pow(10, precision);
}
9. vue启动项目报错。defineConfig is not a function
原因:项目的相关依赖版本不对,可通过 vue upgrade 指令进行升级
10.flex:1 的宽度会被内容元素撑大
解决方法: 在flex:1的的同时,加上overflow: hidden
11.文字换行处理
white-space: pre;
word-wrap:break-word;
word-break:break-all;
12.echart 图表更新数据
myChart.clear();
myChart.setOption(option);
13.扁平转树形
export function tranListToTreeData(list) {
// 1. 定义两个变量
const treeList = [], map = {}
// 2. 建立一个映射关系,并给每个元素补充children属性.
// 映射关系: 目的是让我们能通过id快速找到对应的元素
// 补充children:让后边的计算更方便
list.forEach(item => {
if (!item.children) {
item.children = []
}
map[item.id] = item
})
// 循环
list.forEach(item => {
// 对于每一个元素来说,先找它的上级
// 如果能找到,说明它有上级,则要把它添加到上级的children中去
// 如果找不到,说明它没有上级,直接添加到 treeList
const parent = map[item.pid]
// 如果存在上级则表示item不是最顶层的数据
if (parent) {
parent.children.push(item)
} else {
// 如果不存在上级 则是顶层数据,直接添加
treeList.push(item)
}
})
// 返回
return treeList
}
14.树形转扁平
function flatten(data) {
return data.reduce((prev, cur) => {
prev.push({ id: cur.id, name: cur.name });
if (cur.children) {
prev.push(...flatten(cur.children));
}
return prev;
}, []);
}