vue-router命名视图以及实现页面抽屉功能

发布时间 2023-08-11 08:04:32作者: Meer_zyh

命名视图

首先介绍什么是命名视图,命名视图是vue-router的功能,当我们想在一个页面展示多个视图,而不是嵌套展示时,就可以使用命名视图了;

当使用嵌套路由时,只有一个router-view,而使用命名视图时,可以使用多个router-view,然后给每个router-view设置自己的name,用法:

mian.js

import { createApp } from 'vue'
import App from './App.vue'
import { router } from './router'

const app = createApp(App).use(router)
app.mount('#app')

router.js

使用components定义多个路由,对应的是router-view的name

import { createRouter, createWebHistory } from 'vue-router'
import First from './views/First.vue'
import Second from './views/Second.vue'
import Third from './views/Third.vue'

export const router = createRouter({
  history: createWebHistory(),
  routes: [
    {
      path: '/',
      // a single route can define multiple named components
      // which will be rendered into <router-view>s with corresponding names.
      components: {
        default: First,
        a: Second,
        b: Third,
      },
    },
    {
      path: '/other',
      components: {
        default: Third,
        a: Second,
        b: First,
      },
    },
  ],
})

App.vue

定义多个router-view,添加name属性,没有name默认为default

<template>
  <h1>Named Views</h1>
  <ul>
    <li>
      <router-link to="/">First page</router-link>
    </li>
    <li>
      <router-link to="/other">Second page</router-link>
    </li>
  </ul>
  <router-view class="view one"></router-view>
  <router-view class="view two" name="a"></router-view>
  <router-view class="view three" name="b"></router-view>
</template>

以上内容就实现了命名视图,可以在一个页面展示多个组件的内容

Drawer 抽屉功能

使用element-ui实现抽屉功能

<el-drawer
  title="我是标题"
  :visible.sync="drawer"
  direction="rtl"
  :before-close="handleClose">
  <span>我来啦!</span>
</el-drawer>

element-ui使用了el-drawer组件实现抽屉功能,通过控制drawer属性显示隐藏,title显示标题,可以使用:with-header="false"关闭title的显示,direction控制抽屉的打开方向,befort-colse定义关闭前的回调函数。

还可以实现多层嵌套

<el-drawer
  title="我是外面的 Drawer"
  :visible.sync="drawer"
  size="50%">
  <div>
   <el-button @click="innerDrawer = true">打开里面的!</el-button>
   <el-drawer
     title="我是里面的"
     :append-to-body="true"
     :before-close="handleClose"
     :visible.sync="innerDrawer">
     <p>_(:зゝ∠)_</p>
   </el-drawer>
  </div>
</el-drawer>

使用命名视图实现页面抽屉功能

该方式是使用路由跳转方式实现Drawer功能,实现步骤:

1、在appMain中配置不同name的router-view,当前路由currentRouteName为details并且floaterTag=true时显示详情视图

<section class="app-main">
        <transition name="fade-transform" mode="out-in">
            <keep-alive>
                <router-view :key="key" />
            </keep-alive>
        </transition>
        <!-- details -->
        <transition name="slide-transform" mode="out-in">
            <router-view
                v-if="floaterTag && currentRouteName === 'details'"
                name="details"
                ref="page"
                :key="'details_' + key"
                class="float-right"
            />
        </transition>
</section>

<script>
export default {
   name: 'AppMain',
   computed: {
        // 获取floaterTag和currentRouteName,显示details视图
        ...mapState({
            floaterTag: state => state.app.floaterOpened,
            currentRouteName: state => state.app.currentRouteName
        })
    }
}
</script>

2、store/app.js

const state = {
    floaterOpened: false,
    currentRouteName: ''
}

const mutations = {
    // 打开details视图
    OPEN_FLOATER: (state, crn) => {
        state.floaterOpened = true;
        state.currentRouteName = crn;
    },
    // 关闭details视图
    CLOSE_FLOATER: state => {
        state.floaterOpened = false;
        state.currentRouteName = null;
    }
}

3、router.js 配置components,对应不同name的router-view

{
    path: '/user-center',
    component: Layout,
    hidden: false,
    redirect: 'noredirect',
    meta: { title: '用户中心', icon: 'system' },
    alwaysShow: true,
    children: [{
        path: 'user',
        name: 'SystemUser',
        meta: { title: '用户列表', icon: 'user' },
        components: {
             default: resolve => require(['@/views/user-center/user/index'], resolve),
             details: resolve => require(['@/views/user-center/user/detail'], resolve)
        }
    }]
}

4、点击按钮打开详情抽屉

handleClick(row) {
   this.$router.push({
       name: 'userDetail',
       openType: 'details',
       params: {
           // 其他参数
       }
   });
}

// 跳转name为userDetail的页面

5、detail.vue

<template>
    <div>
        <div>detail页面</div>
        <div class="footer-btns">
            <el-button class="el-icon-back" size="mini" @click="goBack">返回</el-button>
        </div>
    </div>
</template>
<script>
export default {
    name: 'userDetail',  // 设置组件name
    methods: {
        goBack() {
            if (this.floaterTag) {
                this.$store.commit('app/CLOSE_FLOATER'); // 关闭details视图
            } else {
                this.$router.go(-1);
            }
        },
    }
}
</srcipt>

6、permission.js

// 拦截router.push,在store中设置floaterTag和currentRouteName
router.push = function(params) {
    /* params = {
       name: 'userDetail',
       openType: 'details',
       params: {
           ...
       }
    } */
    const toTag = 'details' // 可以动态设置
    if(params.openType === 'details') {
        store.commit('app/OPEN_FLOATER', toTag);
        return;
    }
}

以上就实现了使用命名视图实现页面抽屉功能,基本功能应该和element-ui是一样的,区别是自己封装的,可扩展性更强。