Vue3 implementa aumento y disminución dinámicos de páginas de pestañas

1. Efecto objetivo

        Este blog se enfoca en compartir cómo vue3 realiza el aumento y la disminución dinámicos de las páginas de pestañas. La interfaz del proyecto puede ser fea y la optimización del rendimiento no es perfecta. Por favor, tengan paciencia conmigo. El núcleo de este artículo es comprender la lógica del aumento dinámico . y etiquetas decrecientes. Originalmente, quería usar un video para mostrar el efecto, pero como resultado, el video subido por csdn está bajo revisión unánime, por lo que solo puedo capturar algunas imágenes para que las vea.

        Los comentarios del proyecto son relativamente claros. Ejecute el proyecto usted mismo e interiorícelo lentamente en sus propias cosas. El proyecto utiliza métodos de matriz, sintaxis vue3, vue-router, vuex, clase de vinculación dinámica y conocimiento del operador ternario .

 

 

 

Dos, ejecutar el proyecto

(1) Dirección del proyecto: git clone https://gitee.com/liu-wenxin/operateTags.git

(2) dependencias de instalación de npm install

(3) npm ejecutar servir para ejecutar el proyecto

(4) http://localhost:8080 para acceder al proyecto

3. Proceso de implementación

(1) Estilo de interfaz

<template>
    <!-- 首页 -->
    <div>
        <el-container>
            <!-- 头部 -->
            <el-header>Header</el-header>
            <el-container>
                <!-- 侧边栏 -->
                <el-aside width="200px">
                    <el-menu active-text-color="#6787df" background-color="#252b41" default-active="1" text-color="#fff"
                        router>
                        <el-menu-item index="1">
                            <span>页面1</span>
                        </el-menu-item>
                        <el-menu-item index="2">
                            <span>页面2</span>
                        </el-menu-item>
                        <el-menu-item index="3">
                            <span>页面3</span>
                        </el-menu-item>
                        <el-menu-item index="4">
                            <span>页面4</span>
                        </el-menu-item>
                        <el-menu-item index="5">
                            <span>页面5</span>
                        </el-menu-item>
                        <el-menu-item index="6">
                            <span>页面6</span>
                        </el-menu-item>
                    </el-menu>
                </el-aside>
                <el-main>
                    <!-- tags栏 -->
                    <div class="tagList" v-if="showTags">
                        <ul>
                            <li v-for="(item, index) in tagsList" :class="{ 'active': isActive(item.path) }"
                                :key="index">
                                <router-link :to="item.path" class="tag">
                                    {
   
   { item.name }}
                                </router-link>
                                <el-icon @click="closeTags(index)" class="close">
                                    <Close />
                                </el-icon>
                            </li>
                        </ul>
                        <el-dropdown>
                            <el-button type="primary">
                                标签选项
                                <el-icon>
                                    <ArrowDown />
                                </el-icon>
                            </el-button>
                            <template #dropdown>
                                <el-dropdown-menu>
                                    <el-dropdown-item @click.native="closeOther">关闭其它</el-dropdown-item>
                                    <el-dropdown-item @click.native="closeAll">关闭所有</el-dropdown-item>
                                </el-dropdown-menu>
                            </template>
                        </el-dropdown>
                    </div>

                    <!-- 内容渲染区 -->
                    <keep-alive>
                        <router-view></router-view>
                    </keep-alive>
                </el-main>
            </el-container>
        </el-container>
    </div>
</template>
<script>
import { useStore } from 'vuex'
import { useRoute, useRouter, onBeforeRouteUpdate } from 'vue-router'
import { computed } from 'vue'
export default {
    setup() {
        const route = useRoute();
        const router = useRouter();

        const store = useStore();

        // 获取vuex里面所有的tag
        const tagsList = computed(() => store.state.tagsList)

        // 关闭一个标签
        const closeTags = index => {
            //获取删除的标签的信息
            const delItem = tagsList.value[index];

            //让vuex删除指定的标签
            store.commit('delTagsItem', { index });

            // 如果关闭的是当前标签且标签不止一个,则激活前一个标签,如果关闭的是不是当前标签且标签不止一个,则激活后一个标签
            const item = tagsList.value[index] ? tagsList.value[index] : tagsList.value[index - 1];
            if (item) {
                // 如果删除的是当前标签,则跳往上面item判断好的目标标签的地址
                if (isActive(delItem.path)) {
                    router.push(item.path)
                }
            } else {
                // 如果tagsList只有一个标签,删除了标签就没有标签,则跳转到首页
                router.push("/");
            }
        }

        // 设置标签
        const setTags = (route) => {
            const isExist = tagsList.value.some(item => item.path === route.fullPath)
            if (!isExist) {
                // tag超过5个就删除第一个
                if (tagsList.value.length >= 5) {
                    store.commit('delTagsItem', { index: 0 })
                }
                store.commit('setTagsItem', {
                    name: route.name,
                    path: route.fullPath,
                    title: route.meta.title
                })
            }
        }

        //首次加载页面的时候便添加标签页
        setTags(route);

        // 监听路由变化,在当前页面即将要离开的时候触发
        onBeforeRouteUpdate((to) => {
            setTags(to)
        })

        // 关全部标签
        const closeAll = () => {
            store.commit('clearTags');
            router.push("/");
        }

        // 关闭其它标签
        const closeOther = () => {
            const curItem = tagsList.value.filter(item => {
                return item.path === route.fullPath;
            })
            store.commit('clearTagsOther', curItem);
        }
        // 显示标签栏
        const showTags = computed(() => tagsList.value.length > 0)

        // 判断tag是否被激活,如果被激活就高亮当前标签
        const isActive = path => path === route.fullPath

        return { tagsList, isActive, showTags, setTags, closeAll, closeOther, closeTags }
    }
}
</script>
<style scoped>
.active,
.active .tag {
    background-color: #409eff !important;
    color: #fff !important;
}

.close:hover {
    background-color: #ffffff;
    color: #409eff;
    cursor: pointer;
}

.tag {
    margin: 0 5px;
    height: 100%;
    font-size: 18px;
}

.tagList ul li {
    float: left;
    margin: 3px 5px 2px 3px;
    height: 23px;
    border: 1px solid #e9eaec;
    line-height: 23px;
    border-radius: 3px;
    text-align: center;
    background-color: #fff;
    color: #666;
}

.tagList {
    display: flex;
    justify-content: space-between;
    align-items: center;
    width: 100%;
    background-color: #ffffff;
}

.el-main {
    margin: 0;
    padding: 0;
    background: #efefef;
}

.el-menu-item {
    display: flex;
    justify-content: center;
    font-size: 16px;
}

.el-menu {
    height: 100%;
}

.el-aside {
    height: calc(100vh - 60px);
}

/* 头部样式 */
.el-header {
    height: 60px;
    line-height: 60px;
    background-color: #252b41;
    color: #ffffff;
    text-align: center;
    font-size: 20px;
}
</style>

(2) enrutamiento de enrutador vue

import { createRouter, createWebHistory } from 'vue-router'
const routes = [
  {
    path: '/',
    redirect: '/index',
  },
  {
    path: '/index',
    name: 'index',
    redirect: '/1',
    meta: {
      title: '首页'
    },
    component: () => import( /* webpackChunkName: "index" */ "../views/index.vue"),
    children: [
      {
        path: '/1',
        name: '1',
        meta: {
          title: '页面1'
        },
        component: () => import( /* webpackChunkName: "1" */ "../views/1/1.vue")
      },
      {
        path: '/2',
        name: '2',
        meta: {
          title: '页面2'
        },
        component: () => import( /* webpackChunkName: "2" */ "../views/2/2.vue")
      },
      {
        path: '/3',
        name: '3',
        meta: {
          title: '页面3'
        },
        component: () => import( /* webpackChunkName: "3" */ "../views/3/3.vue")
      },
      {
        path: '/4',
        name: '4',
        meta: {
          title: '页面4'
        },
        component: () => import( /* webpackChunkName: "4" */ "../views/4/4.vue")
      },
      {
        path: '/5',
        name: '5',
        meta: {
          title: '页面5'
        },
        component: () => import( /* webpackChunkName: "5" */ "../views/5/5.vue")
      },
      {
        path: '/6',
        name: '6',
        meta: {
          title: '页面6'
        },
        component: () => import( /* webpackChunkName: "6" */ "../views/6/6.vue")
      }
    ]
  }
]

const router = createRouter({
  history: createWebHistory(),
  routes
})

export default router

(3) vuex

import { createStore } from 'vuex'
export default createStore({
    state: {
        tagsList: []    //存放所有tag标签的数组
    },
    mutations: {
        // 删除一个tag
        delTagsItem(state, data) {
            state.tagsList.splice(data.index, 1)
        },
        //添加一个tag
        setTagsItem(state, data) {
            state.tagsList.push(data);
        },
        // 清除其他tag
        clearTagsOther(state, data) {
            state.tagsList = data;
        },
        // 清除所有tag
        clearTags(state) {
            state.tagsList = []
        }
    }
})

Supongo que te gusta

Origin blog.csdn.net/weixin_42375707/article/details/126217076
Recomendado
Clasificación