23 布局缩略图即成 - udo-bit/naive_admin_pro GitHub Wiki
- 实现通用的标题组件
- 将布局缩略图集成抽屉中
打开setting-drawer下的index.vue的文件中。 添加如下代码:
<script lang="ts" setup>
import CheckboxLayout from './checkbox-layout.vue'
const props = withDefaults(defineProps<{
floatTop?: number | string
drawerWidth?: number | string
layout?: 'side' | 'top' | 'mix'
}>(), {
floatTop: 240,
drawerWidth: 300,
})
const emit = defineEmits(['update:layout'])
const onChange = (val: string) => {
emit('update:layout', val)
}
const layouts = $ref([
{
key: 'side',
title: 'Side Menu Layout',
},
{
key: 'top',
title: 'Top Menu Layout',
},
{
key: 'mix',
title: 'Mix Menu Layout',
},
])
</script>
<template>
<n-drawer-content>
<div class="flex flex-col my-16px">
<span class="mb-16px text-14px font-500">
导航模式
</span>
<n-space size="large">
<template v-for="{ key } in layouts" :key="key">
<CheckboxLayout @click="onChange(key)" :layout="key" :checked="key === layout" />
</template>
</n-space>
</div>
</n-drawer-content>
</template>
我们在base-layout中进行双向绑定布局的变化
<SettingDrawer v-model:layout="layout.layout" />
当我们hover的时候,应该会有一个小手这样会更好一些,所以我们在checkbox-layout中加一个类cursor-pointer�
使得我们在hover的时候触发效果
我们的标题部分在我们的抽屉中是复用程度比较高的,所以我们将这一部分封装成一个组件方便我们后续使用。 我们封装一个setting-container的组件用于放我们的组件内容。
<script lang="ts" setup>
defineProps<{ title?: string }>()
</script>
<template>
<div class="flex flex-col my-16px">
<span class="mb-16px text-14px font-500">
{{ title }}
</span>
<slot />
</div>
</template>
在setting-drawer/index.vue中引入。
<script lang="ts" setup>
import SettingContainer from './settinng-container.vue'
</script>
<template>
<SettingContainer title="导航模式">
<n-space size="large">
<template v-for="{ key } in layouts" :key="key">
<CheckboxLayout :layout="key" :checked="key === layout" @click="onChange(key)" />
</template>
</n-space>
</SettingContainer>
</template>
当我们的鼠标移动到我们的布局缩略图上的时候,我们可以给一个友好的提示,那么我们来实现一下这个功能。 在layout-drawer中(只写了部分修改和添加的代码)
<script lang="ts" setup>
import { CheckOutlined } from '@vicons/antd'
import type { VNodeChild } from '@vue/runtime-core'
const props = withDefaults(defineProps<{
title?: string | (() => VNodeChild)
}>(), {
})
</script>
<template>
<n-tooltip trigger="hover">
<template #trigger>
<n-el
tag="div"
class="cursor-pointer inline-block relative w-44px h-36px b-rd-4px overflow-hidden bg-[var(--pro-admin-layout-content-bg)] shadow-[var(--pro-admin-layout-box-shadow)]"
>
<div
:class="headerClasss"
class="h-25% absolute top-0 w-100%"
/>
<div
v-if="layout !== 'top'"
:class="siderClasss"
class="w-30% absolute left-0 h-100%"
/>
<div v-if="checked" class="absolute bottom--3px right-3px">
<n-icon size="16">
<CheckOutlined />
</n-icon>
</div>
</n-el>
</template>
<span>{{ typeof title === 'function' ? title?.() : title }}</span>
</n-tooltip>
</template>
测试是否正常使用。 当我们点击切换布局的时候发现不生效了是因为我们的click事件继承到了tooltip上,所以我们需要将事件拿到我们的n-el中去:
<script lang="ts" setup>
+ defineEmits(['click'])
</script>
<template>
<n-el
tag="div"
class="cursor-pointer inline-block relative w-44px h-36px b-rd-4px overflow-hidden bg-[var(--pro-admin-layout-content-bg)] shadow-[var(--pro-admin-layout-box-shadow)]"
+ @click="$emit('click', $event)"
>
<div
:class="headerClasss"
class="h-25% absolute top-0 w-100%"
/>
<div
v-if="layout !== 'top'"
:class="siderClasss"
class="w-30% absolute left-0 h-100%"
/>
<div v-if="checked" class="absolute bottom--3px right-3px">
<n-icon size="16">
<CheckOutlined />
</n-icon>
</div>
</n-el>
</template>