el-tabs作为子组件使用页面空白


前言

如果el-tabs是子组件,父组件传值value / v-model为空字符,这个时候在watch中监听value / v-model就会发现监听的数据会被调用为‘0’。一定是作为子组件引用,且在watch进行监听,且vuex没有缓存。就刚进入页面的时候会出现空白页面,点击tab之后就不会再有问题了,因为value / v-model数据更新了。
当然如果你的tabPanes中的code原本就为‘0’,那就不会出现这个问题了,因为value / v-model匹配的到页面。

一、问题展示

base-tabs组件
<template>
  <el-tabs class="base-pane" v-model="activeName">
    <el-tab-pane v-for="pane in tabPanes" :key="pane.code" :label="pane[label]" :name="pane[name]">
      <slot :name="pane[name]" :pane="pane"></slot>
    </el-tab-pane>
  </el-tabs>
</template>

<script>

export default {
  name: 'basePane',
  props: {
    value: {
      type: String,
      default: '',
    },
    tabPanes: {
      type: Array,
      default: [],
    },
    // 标签显示属性
    label: {
      type: String,
      default: 'label',
    },
    // 标签绑定id属性、插槽绑定id
    name: {
      type: String,
      default: 'code',
    },
    // 是否要缓存,页面路由
    tabId: String,
  },
  data() {
    return {
      activeName: this.value,
    };
  },
  mounted() {
  	// 这里是如果store有缓存,将缓存中的数据进行赋值
    if (this.tabId && this.$store.state.setHistoryTab[this.tabId]) {
      this.activeName = this.$store.state.setHistoryTab[this.tabId];
    }
  },
  // watch只有在数据变化了之后才会调用
  watch: {
    value: {
      deep: true,
      handler(val) {
        console.log('value', val);
        this.activeName = val;
      },
    },
    activeName(val) {
      console.log('activeName', val);
      this.$emit('input', val);
      if (this.tabId) {
        this.$store.commit('setHistoryTab', {
          key: this.tabId,
          value: val,
        });
      }
    },
  },
};
</script>


引用
<base-pane v-model="activeName" :tabPanes="tabPanes" :tabId="$route.fullPath">
  </base-pane>
  
activeName:'', // 这里一定是空字符串

getTabsData() {
      this.$post('xxx/xxx/xxx')
        .then((res) => {
          this.tabPanes = res.rspData;
          // 这里是如果store没有缓存,才将数组中的第一个进行赋值
          if (this.tabPanes.length && !this.$store.state.setHistoryTab[this.$route.fullPath]) {
            this.activeName = this.tabPanes[0].code;
          }
        })
        .catch();
    },

打印结果
在这里插入图片描述
子组件这里watch中的activeName竟然是0,这也就导致了,vuex中缓存的数据是0,activeName 找不到对应的code,页面就不会显示了

二、源码分析

在elementui文件夹中的tabs.vue文件中。这里将data和watch放出来就是为了显示currentName是value / v-model的数据,setCurrentName的方法就是对currentName 进行数据修改。

data() {
      return {
        currentName: this.value || this.activeName,
        panes: []
      };
    },

    watch: {
      activeName(value) {
        this.setCurrentName(value);
      },
      value(value) {
        this.setCurrentName(value);
      },
      currentName(value) {
        if (this.$refs.nav) {
          this.$nextTick(() => {
            this.$refs.nav.$nextTick(_ => {
              this.$refs.nav.scrollToActiveTab();
            });
          });
        }
      }
    },
created() {
	// 在if中'',0都会被认为是false。这就会导致currentName会被设置为’0’。base-tabs子组件就会调用watch
      if (!this.currentName) {
        this.setCurrentName('0');
      }

      this.$on('tab-nav-update', this.calcPaneInstances.bind(null, true));
    },

测试结果
在这里插入图片描述

三、解决方案

父组件、子组件两种方式各选一个就可以了。这样可以的原因是因为base-tabs组件里的watch一开始就不会执行,vuex中就不会存储数据,也就会直接执行父组件的【将数组中的第一个进行赋值】的操作。而之前不可以的原因是因为,el-tabs的源码中将空字符串变成了’0’,base-tabs组件里的watch一开始就会执行,vuex中就会存储数据,也就不会直接执行父组件的【将数组中的第一个进行赋值】的操作,而tabPans中的code匹配不到‘0’,页面就不会显示了,但是你点击别的之后页面又会出现了,因为那个时候的activeName就会是正常的code,也就不会再有问题了

base-tabs组件

<script>

export default {
 
  data() {
    return {
      activeName: this.value || '1',
    };
  },
 
};
</script>


父组件引用
activeName:'1',

相关推荐

  1. element-ui el-tabs el-tab-pane 的使用

    2024-05-04 04:32:04       37 阅读
  2. vue el-dialog封装成组件

    2024-05-04 04:32:04       67 阅读
  3. html使用el-table-column />时不能正常渲染出页面

    2024-05-04 04:32:04       28 阅读
  4. el-table-column叠加el-popover使用

    2024-05-04 04:32:04       36 阅读
  5. vue el-dialog封装成组件组件化)

    2024-05-04 04:32:04       26 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-05-04 04:32:04       94 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-05-04 04:32:04       101 阅读
  3. 在Django里面运行非项目文件

    2024-05-04 04:32:04       82 阅读
  4. Python语言-面向对象

    2024-05-04 04:32:04       91 阅读

热门阅读

  1. 62. 不同路径

    2024-05-04 04:32:04       31 阅读
  2. P4_16使用table实现通用的switch分支语句

    2024-05-04 04:32:04       34 阅读
  3. C#核心之概述

    2024-05-04 04:32:04       33 阅读
  4. 代码随想录算法训练营第四十一天

    2024-05-04 04:32:04       33 阅读
  5. Delphi10和12的FDConnection1.GetTableNames参数不一样了

    2024-05-04 04:32:04       37 阅读
  6. 系统架构师英文题目

    2024-05-04 04:32:04       33 阅读
  7. grpc stream发送

    2024-05-04 04:32:04       31 阅读