17 布局功能完善 - udo-bit/naive_admin_pro GitHub Wiki

目标

  1. 侧边栏收缩功能配置
  2. 完善混合布局

侧边栏收缩功能配置

我们先来看一下我们实现一下收缩的功能。在默认情况下,我们没有配置受控模式的侧边栏,所以整个收缩的控制是由于layout-sider自己控制的,接下来我们转换成受控模式的方式,我们在side-layout中先做属性的定义:

const props = withDefaults(defineProps<{
  headerHeight?: number
  logo?: string
  title?: string
  siderWidth?: number
  siderCollapsedWidth?: number
  showSiderTrigger?: boolean | 'bar' | 'arrow-circle'
  inverted?: boolean
  collapsed?: boolean
}>(), {
  headerHeight: 48,
  siderWidth: 240,
  siderCollapsedWidth: 48,
  inverted: false,
})

defineEmits(['update:collapsed'])

然后配置LayoutSider�

<LayoutSider
      :inverted="inverted"
      :collapsed-width="siderCollapsedWidth"
      :collapsed="collapsed"
      :width="siderWidth"
      :show-trigger="showSiderTrigger"
      content-style="padding: 24px;"
      @update:collapsed="($event) => $emit('update:collapsed', $event)"
    >
</LayoutSider>

我们在全局样式配置中也增加一个collapsed

export interface LayoutTheme {
  title?: string
  layout: 'mix' | 'side' | 'top'
  headerHeight: number
  logo?: string
  siderWidth: number
  siderCollapsedWidth: number
  showSiderTrigger: boolean | 'bar' | 'arrow-circle'
 + collapsed: boolean
}

export const layoutThemeConfig: LayoutTheme = {
  title: 'Naive Admin Pro',
  layout: 'side',
  headerHeight: 48,
  logo,
  siderWidth: 240,
  siderCollapsedWidth: 48,
  showSiderTrigger: 'bar',
 + collapsed: false,
}

然后我们在base-layout中使用如下:

<SideLayout
  v-if="layout.layout === 'side'"
+  v-model:collapsed="layout.collapsed"
  :logo="layout.logo"
  :title="layout.title"
  :show-sider-trigger="layout.showSiderTrigger"
  :sider-width="layout.siderWidth"
  :sider-collapsed-width="layout.siderCollapsedWidth"
  >
  <router-view />
</SideLayout>

我们来测试一下收起,发现我们的文字会被挤掉,当我们收起的时候只显示一个图标,其他的我们不需要再显示了。如下:

<Title v-if="!collapsed" :title="title" />

但是我们发现,我们收缩后图标依旧是没有了,原因是我们配置了side的padding我们直接删除掉就可以了。 删掉padding后我们的图标就不居中了,我们需要调整一下整个div的样式。 我们的图标稍微有点小,所以我们将图标的size设置的大一些,设置成30 标题的大小我们调整到22 当我们收缩的时候标题会被换行,我们在Title组件中添加truncate�类型用于当宽度不够的时候,使用省略符号配置。 最终代码如下:

<div class="flex items-center justify-center mt-24px">
    <Logo :src="logo" size="30" />
    <Title v-if="!collapsed" size="22" :title="title" />
</div>

header插槽

我们在header中保留左右两个插槽,分别如下:

<n-layout-header
        class="pro-admin-layout-header flex items-center justify-between px-4"
      >
    <slot name="headerLeft">
      <div />
    </slot>
    <slot name="headerRight">
      <div />
    </slot>
  </n-layout-header>

接下来我们在base-layout中把mix-layout中的右侧插槽放到我们的side-layout中去。

<SideLayout
    v-if="layout.layout === 'side'"
    v-model:collapsed="layout.collapsed"
    :logo="layout.logo"
    :title="layout.title"
    :show-sider-trigger="layout.showSiderTrigger"
    :sider-width="layout.siderWidth"
    :sider-collapsed-width="layout.siderCollapsedWidth"
  >
    <template #headerRight>
      <div>
        测试右侧插槽
      </div>
    </template>
    <router-view />
  </SideLayout>

完善mix-layout

同样的,我们也需要混合布局支持collapsed�的属性,那么我们也来完善一下:

<MixLayout
    v-if="layout.layout === 'mix'"
+    v-model:collapsed="layout.collapsed"
    :logo="layout.logo"
    :title="layout.title"
    :show-sider-trigger="layout.showSiderTrigger"
    :sider-width="layout.siderWidth"
    :sider-collapsed-width="layout.siderCollapsedWidth"
  >
  ...
</MixLayout>

在mix-layout/index.vue中直接拷贝side-layout中的属性

<script lang="ts" setup>
import { LayoutContent, LayoutSider, Logo, Title } from '~/layouts/common'

const props = withDefaults(defineProps<{
  headerHeight?: number
  logo?: string
  title?: string
  siderWidth?: number
  siderCollapsedWidth?: number
  showSiderTrigger?: boolean | 'bar' | 'arrow-circle'
+  collapsed?: boolean
}>(), {
  headerHeight: 48,
  siderWidth: 240,
  siderCollapsedWidth: 48,
})
+ defineEmits(['update:collapsed'])

</script>

<template>
  <n-layout class="h-screen">
    <n-layout has-sider class="pro-admin-layout-content">
      <LayoutSider
        :collapsed-width="siderCollapsedWidth"
        :width="siderWidth"
+        :collapsed="collapsed"
        :show-trigger="showSiderTrigger"
        content-style="padding: 24px;"
+        @update:collapsed="($event) => $emit('update:collapsed', $event)"
      >
        海淀桥
      </LayoutSider>
      <LayoutContent content-style="padding: 24px;">
        <slot />
      </LayoutContent>
    </n-layout>
  </n-layout>
</template>

我们切到混合布局测试

⚠️ **GitHub.com Fallback** ⚠️