1 问题产生原因

项目中遇到一个需求,在一个tabs下面有三个tab-pane,且每个tab-pane列表及查询条件一样,因此后端写了一个接口有三个不同的type;前端写了一个childList组件,在tab-pane中循环调用三次,但初始化页面时,会直接调用三次接口(分别传不同type),这样虽然能实现功能,但初始化的时候只调用默认页面接口即可,不必调所有接口,待优化

2 使用tab-pane自带的:lazy="true"延时加载

<!-- 页面上的tabs -->
<el-tabs class="report-tabs" v-model="activeName">
  <el-tab-pane v-for="item in peReportType" :key="item.valueCode" :label="item.valueName" :name="String(item.valueCode)" :lazy="true">
    <childList ref="childList" :selectedTabName="item.valueCode"></childList>
  </el-tab-pane>
</el-tabs>

// data中
activeName: '1', // activeName必须是字符串
peReportType: [
  {
    valueCode: 1,
    valueName: 'tab1',
  },
  {
    valueCode: 2,
    valueName: 'tab2',
  },
  {
    valueCode: 3,
    valueName: 'tab3',
  },
],

但此时会出现新问题,即tab-pane添加 :lazy="true"属性实现延迟渲染后,此时子组件的selectedTabName可能会显示不正确(selectedTabName为tab1、tab2、tab3的valueCode,刷新页面后会默认选中tab1,若先点击tab3、再点tab2,此时子组件中的2和3的selectedTabName会乱序)

3 使用v-if="activeName == item.valueCode"解决2中的问题

经网上查询得知,在:lazy="true"基础上,子组件上加上v-if判断也能实现延迟加载的问题,经实验不会乱序,但此时会出现另外一个问题,即初始化后,不会乱序,但若是点击tab1,则会再次调用上次调用的接口(初始化调用tab1接口,点击2或者3,则调2或3的接口;此时回来再点1,则先调2或者3再调1接口;此时点击2或者3,则调2或3的接口;再点1,则先调2或者3再调1,如此循环),这样又有了最初多调用接口的问题。

且据网上查询,有人说使用v-if="activeName == item.valueCode,当页面会数据量太大时tab切换效果会卡顿,体验不好。

总之,上述方法均不理想,还不如回到最初状态

4 柳暗花明又一村

上述是自己一直陷在循环的套路里面,其实根据项目需求,完全可以将子组件写在外面(一敲脑袋瓜,自己真笨),如下,然后子组件监听传入不同的type调相应的接口就行!!!

<!-- 页面上的tabs -->
<el-tabs class="report-tabs" v-model="activeName">
	<el-tab-pane v-for="item in peReportType" :key="item.valueCode" :label="item.valueName" :name="String(item.valueCode)"> </el-tab-pane>
</el-tabs>
<childList :selectedTabName="activeName"></childList>

上述就是完美解决方案!!

注意:若在el-tabs上添加@tab-click="handleClick"方法,注意此时是先执行点击事件,再改变activeName的值,所以不能在父组件的handleClick里面执行子组件请求接口的方法,应在子组件中监听selectedTabName的变化

//子组件
 watch: {
   selectedTabName(val) {
     if (val) {
       this.getReportList(1)
     }
   },
 },
Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐