Vuetify—— v-navigation-drawer组件中的transitionend事件

本文展示了如何利用Vuetify的v-navigation-drawer组件创建一个响应式的左侧菜单,该菜单在屏幕尺寸变化时能自动隐藏,并通过顶部导航栏的按钮控制显示。示例中详细给出了MenuList.vue和Header.vue的代码实现,以及store/index.js中的状态管理。当屏幕宽度足够时,菜单默认展开;在小屏设备上,可通过点击顶部的汉堡图标打开和关闭菜单。

v-navigation-drawer组件一般用于管理系统中的左侧菜单,当屏幕视口缩放或屏幕本身小于其一定宽度,其左侧菜单会隐藏掉,这时顶部会展示一个控制其左侧菜单展示按钮,方便使用左侧菜单
当屏幕足够宽时,初始状态展示如下:
在这里插入图片描述
当屏幕缩放到一定宽度时,展示如下:
在这里插入图片描述
点击顶部右侧三条杠的按钮,来控制其左侧菜单展示如下:
在这里插入图片描述
MenuList.vue

<template>
  <div>
    <v-navigation-drawer
      v-model="drawer"
      @transitionend="watchDrawer"
      app
      fixed
      width="260"
      color="#fff"
      class="sidebar"
      style="border-color: rgb(60, 72, 88)"
    >
      <v-app-bar elevation="0" class="sidebar-header">
        <v-badge
          color="#8d6e63"
          :content="$store.state.portal_label"
          offset-x="-5"
          offset-y="14"
          class="menu-title text-center"
        >
          {{ $store.state.system_name }}
        </v-badge>
      </v-app-bar>

      <v-list dense class="nav-list">
        <v-list-item-group color="primary">
          <v-list-item key="dashboard" to="/dashboard" v-ripple="false">
            <span class="iconfont icon-dashboard1"></span>
            <span style="height: 30px; line-height: 30px">系统状态</span>
          </v-list-item>
        </v-list-item-group>
      </v-list>
    </v-navigation-drawer>
  </div>
</template>

<script>

export default {
  name: "MenuList",
  data() {
    return {
      drawer: true,
    };
  },
  methods: {
    watchDrawer() {
      this.$store.commit("drawer_status", { status: this.drawer });
    },
  },
  watch: {
    "$store.state.drawerStatus"() {
      this.drawer = this.$store.state.drawerStatus;
    },
  },
};
</script>

Header.vue:

<template>
  <div class="header-wrapper d-flex justify-space-between">
    <div style="font-weight: 300; line-height: 40px" class="d-flex">
      <span style="color: rgb(141, 110, 99)">XXX管理系统</span>
    </div>
    <ul class="icon-wrapper d-flex" v-if="$store.state.drawerStatus">
      <router-link to="/dashboard">
        <li class="iconfont icon-dashboard1 hearder-icon"></li>
      </router-link>
      <div class="text-center">
        <v-menu bottom offset-y>
          <template v-slot:activator="{ on, attrs }">
            <li
              v-bind="attrs"
              v-on="on"
              class="iconfont icon-person hearder-icon"
            ></li>
          </template>
          <v-sheet class="overflow-hidden header-menu-con">
            <v-list dense expand nav>
              <v-divider class="px-0 my-2"></v-divider>
              <v-list-item to="/auth/sign_out">
                <v-list-item-title class="pl-4"> 登出 </v-list-item-title>
              </v-list-item>
            </v-list>
          </v-sheet>
        </v-menu>
      </div>
    </ul>
    <div v-else>
      <v-app-bar-nav-icon @click="openDrawer"> </v-app-bar-nav-icon>
    </div>
  </div>
</template>

<script>
export default {
  name: "Header"
  methods: {
    openDrawer() {
      this.$store.state.drawerStatus = !this.$store.state.drawerStatus;
    },
  }
};
</script>

store/index.js

state: {
  drawerStatus: true
},
mutations: {
  drawer_status(state, { status }) {
    state.drawerStatus = status;
  }
}

Vuetify:v-navigation-drawer 组件官方文档地址:添加链接描述

<think>好的,用户的问题是关于如何让Vuetify的v-navigation-drawer的内容不占满整个页面。我需要先理解用户的具体需求。用户可能在使用导航抽屉时发现内容区域撑满了整个页面高度,想要调整使其高度自适应内容,而不是占满整个视口。 首先,我需要回忆Vuetify的v-navigation-drawer组件的行为。默认情况下,导航抽屉可能会根据布局设置为高度100%,这样它会占满父容器的高度。如果父容器是v-app或另一个弹性布局组件,可能会继承视口的全部高度,导致导航抽屉的内容也占满整个页面。 接下来,我应该考虑用户可能使用的布局结构。比如,是否嵌套在v-app-bar或其他组件中?是否有使用v-main或v-container?这些布局组件可能影响子组件的高度。用户可能没有正确设置这些布局组件的高度属性,导致内容扩展。 然后,解决方案方面,可能有几种方法: 1. 设置max-height或height属性:直接在导航抽屉上应用内联样式或CSS类,限制其最大高度。但需要注意,这可能会影响响应式设计,或者内容溢出时需要处理滚动。 2. 使用flex布局调整:Vuetify基于Flexbox,可能通过设置父容器的flex-direction和子组件的flex属性来控制高度。例如,让导航抽屉的父容器使用column方向,并设置flex-grow为0,使其仅占用所需空间。 3. 修改Vuetify的默认样式:可能需要覆盖Vuetify组件的默认CSS,比如将height改为auto,或者调整position属性。 4. 使用calc()动态计算高度:结合视口高度和其他元素的高度,动态设置导航抽屉的高度,例如height: calc(100vh - 顶部栏高度)。 此外,需要考虑到用户可能遇到的问题,比如内容过多时的滚动,或者在不同屏幕尺寸下的表现。是否需要内容自适应,还是固定高度?用户可能希望导航抽屉的高度根据内容自动调整,而不是占满整个页面。 还要检查用户提供的代码示例是否有误。比如,用户是否将v-navigation-drawer放在v-main外面,或者是否缺少某些布局容器。正确的Vuetify布局通常包括v-app、v-app-bar、v-navigation-drawer和v-main的组合,这些组件的排列方式会影响子组件的高度。 可能的错误包括没有正确使用v-main作为内容区域,导致导航抽屉和内容区域重叠或高度计算错误。用户可能需要确保导航抽屉和内容区域在布局结构中是兄弟节点,而不是嵌套关系。 最后,需要给出具体的代码示例,说明如何通过CSS或组件属性调整高度。同时,提醒用户测试不同情况,比如移动端响应式布局,内容溢出时的滚动行为等。</think>在 Vuetify 中控制 `v-navigation-drawer` 的高度不占满整页,可以通过以下 **5 种专业方案** 实现。根据不同的使用场景选择最适合的方式: --- ### 方案 1:动态高度绑定(推荐) ```vue <template> <v-navigation-drawer :height="drawerHeight" permanent location="left" > <!-- 内容区 --> <div class="pa-4">自适应高度的内容</div> </v-navigation-drawer> </template> <script setup> import { ref, computed } from 'vue' const contentHeight = ref(300) // 根据实际内容动态计算 const drawerHeight = computed(() => `${contentHeight.value}px`) </script> ``` --- ### 方案 2:CSS 弹性布局控制 ```vue <template> <v-app> <v-navigation-drawer class="custom-drawer"> <!-- 内容区 --> </v-navigation-drawer> <v-main style="min-height: 100vh"> <!-- 主内容区 --> </v-main> </v-app> </template> <style> .custom-drawer { height: auto !important; /* 取消固定高度 */ min-height: 200px; /* 设置最小高度 */ max-height: 80vh; /* 设置最大高度 */ overflow-y: auto; /* 内容溢出时滚动 */ display: flex; flex-direction: column; } </style> ``` --- ### 方案 3:响应式断点控制 ```vue <template> <v-navigation-drawer :height="$vuetify.display.mobile ? 'auto' : '60vh'" > <!-- 内容区 --> </v-navigation-drawer> </template> <style> /* 移动端特殊处理 */ @media (max-width: 600px) { .v-navigation-drawer { max-height: 300px !important; } } </style> ``` --- ### 方案 4:嵌套滚动容器 ```vue <template> <v-navigation-drawer style="height: auto"> <v-card class="overflow-y-auto" :style="{ maxHeight: scrollMaxHeight }" > <v-card-text> <!-- 长内容会自动滚动 --> <div v-for="n in 50" :key="n">Item {{ n }}</div> </v-card-text> </v-card> </v-navigation-drawer> </template> <script setup> const scrollMaxHeight = computed(() => `${window.innerHeight - 100}px` // 留出顶部空间 ) </script> ``` --- ### 方案 5:组合布局技巧 ```vue <template> <v-app> <v-layout> <v-navigation-drawer style="position: absolute; height: fit-content" > <!-- 绝对定位的抽屉 --> </v-navigation-drawer> <v-main style="margin-left: 256px"> <!-- 主内容区偏移 --> </v-main> </v-layout> </v-app> </template> ``` --- ### 关键实现原理 1. **高度计算策略** ```javascript // 动态计算可用空间 const availableHeight = window.innerHeight - headerHeight - footerHeight ``` 2. **CSS 定位技巧** ```css .custom-drawer { position: sticky; /* 粘性定位 */ top: 64px; /* 与顶部栏间距 */ align-self: flex-start; /* 防止高度拉伸 */ } ``` 3. **响应式监听** ```javascript // 监听窗口变化 window.addEventListener('resize', updateHeight) ``` --- ### 专业增强技巧 #### 1. 内容高度自动跟踪 ```vue <script setup> import { useElementSize } from '@vueuse/core' const drawerRef = ref(null) const { height } = useElementSize(drawerRef) watch(height, (newVal) => { if (newVal > window.innerHeight * 0.8) { drawerRef.value.style.maxHeight = '80vh' } }) </script> <template> <v-navigation-drawer ref="drawerRef"> <!-- 动态内容 --> </v-navigation-drawer> </template> ``` #### 2. 过渡动画优化 ```css .v-navigation-drawer { transition: height 0.3s cubic-bezier(0.4, 0, 0.2, 1); } ``` #### 3. 边界情况处理 ```javascript // 确保最小可操作高度 const safeHeight = computed(() => Math.max(contentHeight.value, 200) // 不低于200px ) ``` --- ### 常见问题解决方案 #### Q1:底部内容被遮挡 ```css .v-navigation-drawer__content { padding-bottom: 48px; /* 留出底部空间 */ } ``` #### Q2:移动端滚动冲突 ```vue <v-navigation-drawer touchless <!-- 禁用触摸滑动 --> > <div class="scroll-wrapper"> <!-- 自定义滚动区域 --> </div> </v-navigation-drawer> ``` #### Q3:与 v-app-bar 联动 ```vue <template> <v-app-bar height="64"></v-app-bar> <v-navigation-drawer :style="{ top: '64px', height: 'calc(100vh - 64px)' }" > </v-navigation-drawer> </template> ``` --- ### 最佳实践推荐 ```vue <template> <v-app> <v-app-bar color="primary" density="compact"></v-app-bar> <v-navigation-drawer :width="256" :height="drawerHeight" permanent class="smart-drawer" > <div class="content-wrapper"> <!-- 抽屉内容 --> </div> </v-navigation-drawer> <v-main style="margin-left: 256px"> <!-- 主内容区 --> </v-main> </v-app> </template> <script setup> import { useDisplay } from 'vuetify' const { mobile } = useDisplay() const drawerHeight = computed(() => mobile.value ? 'auto' : 'calc(100vh - 64px)' ) </script> <style> .smart-drawer { transition: all 0.3s ease; } .smart-drawer .content-wrapper { padding: 16px; max-height: calc(100vh - 80px); overflow-y: auto; } @media (max-width: 600px) { .smart-drawer { width: 100% !important; max-height: 60vh; } } </style> ``` 这个方案实现了: 1. 桌面端固定高度(扣除顶部栏) 2. 移动端自动高度 + 最大高度限制 3. 内容区域自适应滚动 4. 响应式布局适配 5. 平滑过渡动画 通过这种方式,可以在保持导航抽屉功能完整性的同时,实现高度智能适配不同设备和内容长度的需求。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值