问题: 菜单管理页面,打开耗时7.8秒
有2200多个菜单, 请求接口返回700k的数据, 领导说返回的数据量太大了, 让改造下.
过程:
尝试一: 想着能少改就少改的原则. 700k你嫌大, 那咱就压缩下数据传输. 修改完之后接口返回数据size60多k, 但是管理菜单打开的时间只优化了一点. 这个压缩传输的博客还没写//TODO
尝试二: 其实线上服务器资源的这个接口, 在命中缓存的情况下查询耗时也不算长, 主要时间耗费在渲染表格上面. 另外结合业务:菜单管理. 只有管理员才有权限,一般是有新功能上线新增菜单, 或者下线菜单, 并没有一次性加载所有菜单的必要.
所以我们将菜单(table)加载改为懒加载. 改需求结合ElementUi组件很容易实现, 可以去查看文档. 大体思路就是 初始化打开页面时只显示第一级菜单, 用户点击展开菜单之后往后端发送请求,然后加载出一级子菜单. 后台只用有一个根据菜单id查询他子菜单的接口就可以
<el-table:data="tableData1"style="width: 100%" row-key="id"borderlazy:load="load" :tree-props="{children: 'children', hasChildren: 'hasChildren'}"><el-table-columnprop="date"label="日期"width="180"></el-table-column><el-table-columnprop="name"label="姓名"width="180"></el-table-column><el-table-columnprop="address"label="地址"></el-table-column></el-table>data() {return {tableData1: [{id: 1,date: '2016-05-02',name: '王小虎',address: '上海市普陀区金沙江路 1518 弄'}, {id: 2,date: '2016-05-04',name: '王小虎',address: '上海市普陀区金沙江路 1517 弄'}, {id: 3,date: '2016-05-01',name: '王小虎',address: '上海市普陀区金沙江路 1519 弄',hasChildren: true //该字段为true的,父菜单才有下级的小箭头可以点击,代表还有子菜单}, {id: 4,date: '2016-05-03',name: '王小虎',address: '上海市普陀区金沙江路 1516 弄'}]}
}methods: {load(tree, treeNode, resolve) { //tree 我们点击的行数据...调用接口获得改菜单的子菜单 getChildMenu(tree.id).then((res) => { //getChildMenu是我们自己的调用后台的封装resolve( //resolve是组件的res.content //根据自己的格式,将查到的子菜单数组填充)})}
}
改完很OK, 秒开, 加载很快. 子菜单加载一次之后就被缓存了,在怎么点击也不会重新去请求后台. 这个也导致了在我们增删改排序等操作菜单之后, 页面对应的菜单节点没有更新, 实际数据已变更. 整体刷新一下页面的话会显示正确, 不过不可能每次更新之后,强制刷新页面吧.
那我们要做的就很清晰了: 修改了哪一行, 就拿到这一行数据的PID, 然后去调用接口,查到这个PID下一级子菜单,查到数据之后塞回去就行了. 接口和页面加载的那个接口是复用的, 无非页面加载的时候PID传的是0.
reflushtable(crud,pid){ //解决菜单懒加载时. 更新,添加,删除 排序不更新的情况crudMenu.getMenusByPid(pid).then((res) => {this.$set(this.$refs.table.store.states.lazyTreeNodeMap, pid, res.content)})
},//this.$refs.table 注意这个table是你的table属性:ref的名字.
//没有一丝丝技巧, 全靠面向搜索引擎, 这玩意藏那么深谁能找到^^
剩下的就根据自己的实现, 在新增,删除,编辑方法之后,或钩子之后. 去拿父ID查数&set.
在提一嘴 如果有批量删除功能的话, 要注意拿PID循环调用下, 要不然会存在刷新不到的地方. 当然最好将PID去重下.