Vue3 utilise la communication des composants parent-enfant pour implémenter la fonction d'onglet de page

1. Processus général

2. Connaissances Vue3 utilisées

1. Communication des composants

(1) De père en fils

Dans vue3, les composants parents utilisent la liaison et les accessoires pour transmettre des valeurs aux composants enfants.

Étant donné que le tableau d'onglets doit être placé dans la page parent,


  data(){
    return {
      tabs: []
    }
  },

La barre supérieure doit donc récupérer le tableau d'onglets de la page parent.

Définissez d'abord les accessoires dans la page à onglet à recevoir

  props:{
    tabs: Array // 声明一个 props,指定数据类型为数组
  },

Ensuite, liez-le avec le caractère :binding dans la balise de page enfant de la page parent.

  <NavBar :tabs="tabs" ></NavBar>

De cette façon, le tableau d'onglets de la page parent peut être transmis à la page enfant.

(2) Le Fils donne au Père

Comme il existe un itinéraire dans la page enfant pour accéder à une nouvelle page, vous devez ajouter un onglet, c'est-à-dire ajouter la nouvelle page en tant qu'onglet au tableau d'onglets, et le tableau d'onglets est placé dans la page parent, donc l'enfant doit transmettre la valeur au parent.

L'enfant transfère la valeur au parent en appelant une méthode utilisant this.$emit("communication name", data)

Par exemple, l'opération d'ajout d'un onglet ici est

     this.$emit("addtab",tab)

Utilisez ensuite @ dans la balise enfant de la page parent pour accepter le nom de communication et lier la méthode à appeler.

 <router-view  @addtab="addTab"></router-view>

 En même temps, transmettez les données dans la méthode en tant que paramètre de données.

    addTab(data) {
      //最简单的push操作,还没完成其它逻辑
      this.tabs.push(data);

    }

3. Mettre en œuvre la logique globale

1. Dans la page parent

(1) Écrivez la logique pour ajouter des onglets
    addTab(data) {
      // this.tabs.push(data);
        // 判断是否已存在相同的 title 和 route
        const exists = this.tabs.some(tab => tab.title === data.title && tab.route === data.route);
        if (!exists) {
          this.tabs.forEach(tab => {
            tab.selected = false;
          });
          this.tabs.push(data);
        }else{
          this.tabs.forEach(tab => {
            tab.selected = tab.title === data.title && tab.route === data.route;
          });
        }

        // 更新浏览器缓存
      this.saveTabsToLocalStorage()
    }
(2) Écrivez la logique de fermeture de l'onglet
    closeTab(index) {
      this.tabs.splice(index, 1); // 从数组中移除页签

      if (this.tabs.length > 0) {
        this.tabs.forEach(tab => {
          tab.selected = false;
        });
        // 如果还有其他选项卡,跳转到最后一个选项卡的路由
        const lastTab = this.tabs[this.tabs.length - 1];
        this.$router.push(lastTab.route);
        this.tabs[this.tabs.length - 1].selected=true;
      } else {
        // 如果没有选项卡了,跳转到默认的首页路由
        this.$router.push("/1/C");
      }

      // 更新浏览器缓存
      this.saveTabsToLocalStorage()
    },
(3) Mettre en cache le tableau d'onglets dans le navigateur et le charger à partir du cache
 mounted() {
    this.loadTabsFromLocalStorage();
  },
  methods:{
    // 缓存到本地
    saveTabsToLocalStorage() {
      localStorage.setItem('tabs', JSON.stringify(this.tabs));
    },
    // 从缓存加载
    loadTabsFromLocalStorage() {
      const storedTabs = localStorage.getItem('tabs');
      if (storedTabs) {
        this.tabs = JSON.parse(storedTabs);
      }
    },
  }

Mettez en cache les données de l'onglet dans le navigateur. Lorsque la page est actualisée, l'état de l'onglet conserve l'état actuel et ne sera pas effacé.

(4) Communiquer avec la barre supérieure
<NavBar :tabs="tabs" @asideCollapse="collapse" @closetab="closeTab">
(5) Communiquer avec les sous-pages qui doivent générer des onglets
<router-view  @addtab="addTab"></router-view>

2. Barre supérieure

(1) Onglet Rendu
    <div class="top-bar">
      <!-- 渲染页签 -->
      <div
          v-for="(tab, index) in tabs"
          :key="index"
          :class="['tab', { 'selected': tab.selected }]"
          @click="switchTab(tab)"
      >
        {
   
   { tab.title }}
        <span class="close-btn" @click.stop="closeTab(index)">×</span>
      </div>
    </div>
(2) Style d'onglet d'écriture
<style lang="scss" scoped>
 
.top-bar{
  display: flex;
  margin-left: 20px;
  caret-color: transparent; /*去除鼠标光标*/
  width: 100vw;
  overflow-x: auto; /* 允许横向滚动 */
  //overflow: hidden;

  div:hover{
       cursor:pointer;
    }

  div:not(:first-child){
    margin-left: 10px;
  }

  div{
    display: flex;
    justify-content: center;
    align-items: center;
    padding: 5px;
    font-weight: 500;
    font-size: 14px;
    color: #606266;
    border: 1px solid #DCDFE6;
    border-radius: 4px;
    //width: 100%;
    height: 30px;

    white-space: nowrap; /* 防止内容换行 */
    span{
      width: 15px;
      height: 15px;
      margin-left: 4px;
      display: flex;
      align-items: center;
      justify-content: center;


    }


  }

  .tab{
    background-color: #eeeeee;

    span:hover{
      background: linear-gradient(rgba(96, 98, 102, 0.1), rgba(96, 98, 102, 0.1)); /* 在悬停时更改透明度 */
    }
  }

  .selected{
    background-color: #c6fce5;

  }
}

</style>
(3) Accepter les données de la page parent
  props:{
    tabs: Array // 声明一个 props,指定数据类型为数组
  },
(4) Envoyer une demande de fermeture de l'onglet vers la page parent
    // 关闭页签
    closeTab(index) {
      this.$emit("closetab",index)
    },

3. Sous-page

(1) Envoyer une demande d'ajout d'un onglet à la page parent
  methods:{
   addTab(tab){
     this.$emit("addtab",tab)
   }

  }
 (2) Demandes de liaison d'étiquettes avec exigences de routage de saut

 Par exemple, les éléments de menu

        <el-menu-item index="/1/C" 
        @click="addTab({
        title: '模拟计算', // 页面标题
        route: '/1/C', // 路由
        selected: true // 设置选中状态
        })"
        >

4. Effet d'affichage

5. Erreurs possibles

1. Il s'exécute sans erreur dans l'environnement local et sera signalé après avoir été déployé dans l'environnement de production.

TypeError : Impossible de lire les propriétés de null (lecture de 'insertBefore' )

solution 

(1) Le tableau d'onglets de rendu v-for dans le composant de la barre supérieure NavBar ne détermine pas si les onglets sont vides.
(2) Basculez vue vers la version ([email protected]) pour le corriger.
npm i [email protected]

Je suppose que tu aimes

Origine blog.csdn.net/qq_53478650/article/details/132397198
conseillé
Classement