Vue3 utiliza la comunicación de componentes padre-hijo para implementar la función de pestaña de página

1. Proceso general

2. Conocimiento de Vue3 utilizado

1. Comunicación de componentes

(1) Padre a hijo

En vue3, los componentes principales utilizan enlaces y accesorios para pasar valores a los componentes secundarios.

Debido a que la matriz de pestañas debe colocarse en la página principal,


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

Entonces, la barra superior necesita obtener la matriz de pestañas de la página principal.

Primero defina los accesorios en la pestaña para recibir

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

Luego vincúlelo con el carácter de enlace en la etiqueta de la página secundaria en la página principal.

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

De esta manera, la matriz de pestañas de la página principal se puede pasar a la página secundaria.

(2) El Hijo da al Padre

Debido a que hay una ruta en la página secundaria para saltar a una nueva página, debe agregar una pestaña, es decir, agregar la nueva página como una pestaña a la matriz de pestañas, y la matriz de pestañas se coloca en la página principal, por lo que el niño necesita pasar el valor al padre.

El niño transfiere el valor al padre llamando a un método usando this.$emit("nombre de comunicación", datos)

Por ejemplo, la operación de agregar una pestaña aquí es

     this.$emit("addtab",tab)

Luego use @ en la etiqueta secundaria de la página principal para aceptar el nombre de la comunicación y vincular el método que se llamará.

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

 Al mismo tiempo, pase los datos al método como parámetro de datos.

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

    }

3. Implementar la lógica general.

1. En la página principal

(1) Escribe la lógica para agregar pestañas.
    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) Escribe la lógica para cerrar la pestaña.
    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) Almacenar en caché la matriz de pestañas en el navegador y cargarla desde el caché
 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);
      }
    },
  }

Almacene en caché los datos de la pestaña en el navegador. Cuando se actualiza la página, el estado de la pestaña conserva el estado actual y no se borrará.

(4) Comunicarse con la barra superior
<NavBar :tabs="tabs" @asideCollapse="collapse" @closetab="closeTab">
(5) Comunicarse con subpáginas que necesitan generar pestañas
<router-view  @addtab="addTab"></router-view>

2. barra superior

(1) Pestaña de renderizado
    <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) Escribir estilo de pestaña
<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) Aceptar datos de la página principal
  props:{
    tabs: Array // 声明一个 props,指定数据类型为数组
  },
(4) Enviar una solicitud para cerrar la pestaña de la página principal
    // 关闭页签
    closeTab(index) {
      this.$emit("closetab",index)
    },

3. Subpágina

(1) Enviar una solicitud para agregar una pestaña a la página principal
  methods:{
   addTab(tab){
     this.$emit("addtab",tab)
   }

  }
 (2) Solicitudes de vinculación de etiquetas con requisitos de enrutamiento de salto

 Por ejemplo, elementos del menú.

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

4. Efecto de visualización

5. Posibles errores

1. Se ejecuta sin errores en el entorno local y se informará después de su implementación en el entorno de producción.

TypeError: No se pueden leer las propiedades de null (leyendo 'insertBefore' )

solución 

(1) La matriz de pestañas de representación v-for en el componente de la barra superior NavBar no determina si las pestañas están vacías.
(2) Cambie vue a la versión ([email protected]) para solucionarlo.
npm i [email protected]

Supongo que te gusta

Origin blog.csdn.net/qq_53478650/article/details/132397198
Recomendado
Clasificación