周日-选项卡切换中图表 无法自适应 ?

昨天写的 tabs标签页切换中存在一个问题,除了默认展示的页面,其他页面也可以切换,只是发生了坍缩,挤成了一小块。

  • 经过这两天的工作,我总结的问题所在 及注意点。

    • tabs是一次性渲染完毕的
    • 注意点: 图表的展示需要一个宽高确定的容器

首先 tabs 是一次性渲染完毕的

  • 我是这样理解的:
  • 图表不是真正意义上的坍缩,而是在一次性渲染的时候他的宽高就那么大,所以图也就那么大. 要想证明也不难,看看图表组件内部的 created 钩子在点击的时候会不会执行就可以。
    • 执行-就证明它是会在点击的时候重新构建的。
js 复制代码
<template>
  <div class="charts" ref="chart"></div>
</template>

<script>
import * as echarts from "echarts";
export default {
  name: "Chart",
  props: {/* ··· */},
  created(){
    console.log('我被创造出来了!');
  },
  data() {
    return {/* ··· */};
  },
  mounted() {/* ··· */},
  methods: {/* ··· */},
  watch: {/* ··· */},
};
</script>

<style scoped lang="less"> /* ··· */ </style>
  • 很显然,一经挂载它就执行了9次说明它只会在最初的时候会对这些数据进行处理。
  • 通过显示的小图,其实也可以窥见到,每一项的 tab-pane 是有多大(挺有趣的),虽然没啥用。

  • 从上面可以得到两个结论

    • 1.首次展示是正常的。
    • 2.渲染是一次性渲染完毕的。
  • 也就是说只有我们看见的时候渲染的组件显示是 "正常" 的。

其次 图表的展示需要 宽高确定的容器

  • 容器的高度必须给确定值 百分比无效( el-input的宽度也一样 );
  • 无效的情况

    • 这个问题我在遇见的时候,迷迷糊糊不清楚原因,临时解决是给他设置了 vw 和 wh ( 最大值100 和百分比的用法一样 不过他是 以屏幕大小作为计算依据的 )
    • 当时只想着不能给死值,且是在 el-card 的包裹里面 ,怎么设置怎么不生效别说撑开了,让它显示都难。
      • el-card 设置样式有一个设定好的方法 :body-style="{width:"100%",/*···*/}" ; 这也是后两天才发现的。( 去翻的文档)

最后 是解决方式

  • 既然只有首次挂载,看的见的才能 "正常" 那就每次挂载,都让它 卸载再挂载一次。
  • 我采用的方式也是最简单的,就是 v-if
    • v-if 为true 时显示组件 为false 时不显示,且dom信息直接消失,是删除不是隐藏。
    • v-show 是隐藏 不是消失 (我认为:在大量数据 且切换频繁的组件用 v-show 比较合适),这里并不能起到效果
    • 只有把组件删除掉,才会在挂载的时候 触发挂载,不然一直都在的哪里来的挂载。
  • 我选择在 点击事件都是用的 为图表更改数据的方法里(省事,只写一次);
js 复制代码
editOption( index = 0){

      this.chartOption.xAxis.data = Object.keys(this.titleContent2[index]);

      this.chartOption.series.data = Object.values(this.titleContent2[index]);

      this.chartShow = false

      clearTimeout(this.time)

      this.time = setTimeout(()=>{

        this.chartShow = true;

      },200);

    }

问题出来了,他在切换的时候会缩进去。 原因是切换的时候,它的内容(图表)是销毁了的,没有东西撑着,它就缩进去了。 给tabs 设置固定高度,百分比无效

以下就是完整的代码了!

js 复制代码
<template>
  <div class="box">
    <h2 style="color:rgb(122, 105, 204)">el-tabs 渲染</h2>
    <el-tabs v-model="value" @tab-click="handleClick">
      <el-tab-pane v-for="(item,index) in titleList1" :key="index"
        :label="item"
        :name="item"
      >
        <el-tabs style="height:240px" v-model="value2" @tab-click="handle2Click">
          <el-tab-pane v-for="(arrItem,index) in titleList2" :key="index"
            :label="arrItem"
            :name="arrItem"
          >
            <Chart v-if="chartShow" class="chartHeight"
              :option="chartOption"
            />
          </el-tab-pane>
        </el-tabs>
      </el-tab-pane>
    </el-tabs>
  </div>
</template>

<script>
import axios from 'axios';
import Chart from "../../components/Chart.vue";
export default {
  name: "RenderingForObjectForm",
  data() {
    return {
       chartOption: {
         xAxis: { data: [] },
         series: {
           type: "line",
           smooth: true,
           data: [],
         },
       },
      objData:{},
      // 渲染一级 标题的数据
      titleList1:[],
      // 一级 标题对应的数据
      titleContent1:[],
      titleList2:[],
      titleContent2:[],
      value: "",
      value2:"",

      time:'',
      chartShow:true,
    };
  },
  mounted(){
    // 我是用了mock
    this.getList();//获取数据 的方法
  },
  methods: {
    async getList(){// 初始化
      // 我们通过发请求,拿到了数据,并赋值给了 objData
      let data = await axios.get("/web/getList")
      this.objData = data.data
      console.log(this.objData);
      // 解析出来渲染一级 标题的数据
      this.titleList1 =  Object.keys(this.objData);
      this.titleContent1 = Object.values(this.objData);
        // 首先设置 一级title的默认值
        this.value = this.titleList1[0];
        this.setList1()
    },
    handleClick() { // 点击事件
      this.setList1()
    },
    handle2Click() {
      this.titleList1.forEach((item,index)=>{
        if(item == this.value){
          this.titleList2.forEach((item,index)=>{
            if(item == this.value2){
              this.editOption(index)
            }
          })
        }
      })
    },
    setList1(){
      this.titleList1.forEach((item,index)=>{
        if(item == this.value){
          let t2 = this.titleContent1[index]; 
            this.titleList2 = Object.keys(t2);
            this.titleContent2 = Object.values(t2);
            this.value2 = this.titleList2[0]
            this.editOption()
        }
      })
    },
    editOption( index = 0){
      this.chartOption.xAxis.data = Object.keys(this.titleContent2[index]);
      this.chartOption.series.data = Object.values(this.titleContent2[index]);
      this.chartShow = false
      clearTimeout(this.time)
      this.time = setTimeout(()=>{
        this.chartShow = true;
      },200);
    }
  },
  components: { Chart },
};
</script>

<style scoped lang="less">
.chartHeight {
  height: 200px;
  width: 100%;
}
</style>

OK 晚安!!!

相关推荐
尾善爱看海5 小时前
Vue 面试收官篇:SSR、性能优化落地、30 道高频面试题精讲(附标准答案)
前端·javascript·vue.js·面试·vue
weixin_BYSJ19875 小时前
【计算机毕设】基于SpringBoot与Vue的文物保护档案管理系统08621
vue.js·spring boot·spring cloud·微服务·架构·django·课程设计
Bs_MoneyMagnet5 小时前
基于springboot+vue的个人健康管理系统的设计与实现 源码+文档
java·vue.js·spring boot·后端·vue3·springboot3·计算机毕业设计
驳是6 小时前
一个组件,提升 react-router 开发的幸福感
前端·preact
GreenTea6 小时前
OpenAI Agents API 上手实测:一次调用把整个 agent loop 甩给 OpenAI
前端·后端·算法
星云API技术支持6 小时前
企业微信二次开发:群权限设置、成员管理与群资料维护的接口组合实践
java·前端·企业微信
京东云开发者6 小时前
81.8 秒的视频,我们改了 15 个版本:一次纯 Codex 驱动的 AI-native 视频实践
前端·aigc
Csvn7 小时前
TypeScript 大型项目架构:从单体 tsconfig 到分层可扩展的工程
前端
Bs_MoneyMagnet8 小时前
基于springboot+vue的心理咨询预约与随访平台的设计与实现 源码+文档
vue.js·spring boot·后端·spring·毕业设计·旅游·计算机毕业设计
计算机魔术师8 小时前
Dario Amodei 发文呼吁为前沿 AI 降速并提出三点计划
前端