问题描述
项目前台有个tab标签页切换,三个TabPane标签,分别挂载三个不同的组件,三个组件中都有网络请求,且第三组件中数据量大无分页,需要进行前端显示优化——Tab页怎样进入页面时只请求默认显示项的数据?
HTML代码大致如下,pending-table、warning-select、threshold-table分别是TabPane标签中的三个组件:
<Tabs>
<TabPane label="等待处理" name="0">
<pending-table></pending-table>
</TabPane>
<TabPane label="预警查询" name="1">
<warning-select></warning-select>
</TabPane>
<TabPane label="预警阀值" name="2">
<threshold-table></threshold-table>
</TabPane>
</Tabs>
说一下需求:
- 页面加载时,默认显示的Tab页是“等待处理”,pending-table中显示网络请求回来的数据,页面渲染需要流畅;
- “预警查询”和“预警阀值”页面中的数据,需要在鼠标点击切换到对应的Tab页时再做请求,不点击不请求。
解决方法
解决思路:
过程1
首先的想法是点击对应标签页时传值给组件:
仔细查看关于Tabs的官方文档的API,API中提供了一个Tabs标签的on-click事件
当点击TabPane时被触发,@on-click是写在<Tabs>
标签中,使用时要调用方法解决
思路就是点击tab标签页时获得当前标签页的标志值,使用这个值控制子组件v-if隐藏,这个标志值默认为0,点第二个标签时变成1,点第三个标签变成2。
再继续看,API中还提供了v-model双向绑定的值,比使用on-click方便
给Tabs绑定一个双向绑定的值,这时value的值就是你点击的TabPane所对应的name:
<Tabs v-model="value">
<TabPane label="等待处理" name="0">
<pending-table></pending-table>
</TabPane>
<TabPane label="预警查询" name="1">
<warning-select></warning-select>
</TabPane>
<TabPane label="预警阀值" name="2">
<threshold-table></threshold-table>
</TabPane>
</Tabs>
data() {
return {
value: '',
}
},
过程2
现在已经拿到了当前点击的TabPane所对应的name,进行下一步“用name值控制组件显隐”
<TabPane label="预警查询" name="1">
<warning-select v-if=“value === ’1‘”></warning-select>
</TabPane>
以上代码可以控制组件显隐,但是在切换Tab页时血卡无比,控制显隐的方法Pass掉。
过程3
换了一种想法,决定将name值传给子组件然后在子组件中,控制网络请求是否执行。
使用父传子将name值传给子组件
<Tabs v-model="value">
<TabPane label="等待处理" name="0">
<pending-table></pending-table>
</TabPane>
<TabPane label="预警查询" name="1">
<warning-select :getClick="value"></warning-select>
</TabPane>
<TabPane label="预警阀值" name="2">
<threshold-table :getClick="value"></threshold-table>
</TabPane>
</Tabs>
然后在子组件中编写监听函数监听value值的变化:
其中this.channellevelList.length是渲染warning-select数据的data,this.query_channellevelList();是网络请求
watch:{
getClick(value) {
if (this.channellevelList.length === 0 && value === '2') {
this.query_channellevelList();
}
}
},
点击标签页时,watch可以监听到value的变化,如果渲染数据的data长度为0(即还未开始渲染数据),执行网络请求。
这样做的意义是不用需要二次请求,数据可以保存在本地。
缺点:第一次切换数据量大的页面请求时还是会血卡无比,但是只会卡一次。