文章归档:https://www.yuque.com/u27599042/coding_star/oglrqteg8fzvvzn0
[自定义 Vue 组件] 响应式顶部导航栏(1.0) TopNav:https://www.yuque.com/u27599042/coding_star/hzltsltxgavwx8u2
组件效果示例
组件所依赖的子组件
- [自定义 Vue 组件] 小尾巴 Logo 组件(2.0) TailLogo:https://www.yuque.com/u27599042/coding_star/mluie83zdzaf40sy
- [自定义 Vue 组件] 小尾巴下拉菜单组件(2.0) TailDropDown:https://www.yuque.com/u27599042/coding_star/kcoem6dgyn8drglb
组件所依赖第三方库
@vueuse/core
pnpm i @vueuse/core
组件所依赖的 CSS 变量
在 src 目录下,创建 styles 目录,在其中创建 tailComponentsThemeStyles 目录,在 tailComponentsThemeStyles 目录中新建 light.css 与 dark.css 文件,在其中声明组件所依赖的和主题样式相关的 CSS 变量
/*
* 和小尾巴组件相关的亮色主题样式 CSS 变量
*/
:root[class*='light'] {
/*
* 小尾巴顶部导航栏组件样式变量
*/
/* 小尾巴顶部导航栏组件背景颜色 */
--tail-top-nav-bgc: #efefef99;
/* 小尾巴顶部导航栏组件文字颜色 */
--tail-top-nav-font-color: #333333;
}
/*
* 和小尾巴组件相关的暗色主题样式 CSS 变量
*/
:root[class*='dark'] {
/*
* 小尾巴顶部导航栏组件样式变量
*/
/* 小尾巴顶部导航栏组件背景颜色 */
--tail-top-nav-bgc: #454545;
/* 小尾巴顶部导航栏组件文字颜色 */
--tail-top-nav-font-color: #efefef;
}
在 index.html 文件中的 html 元素上添加 light 或 dark 类名
<html lang="zh-CN" class="light">
在 main.js 文件中引入组件所依赖的和主题样式相关的 CSS 变量
vue 项目中配置 src 目录别名:https://www.yuque.com/u27599042/coding_star/ogu2bhefy1fvahfv
import '@/styles/tailComponentsThemeStyles/light.css'
import '@/styles/tailComponentsThemeStyles/dark.css'
配置 sass 预处理
https://www.yuque.com/u27599042/coding_star/ua8sgyngldtaa2re
组件源码
在 src/components 目录下,创建 TailTopNav.vue 文件,在其中编写组件
<script setup>
import {useResizeObserver} from '@vueuse/core'
import {ref, onMounted} from 'vue'
/**
* 接收父组件传递的参数
* @type {Prettify<Readonly<ExtractPropTypes<{}>>>}
*/
const props = defineProps({
// 小尾巴侧边导航栏组件展示按钮点击事件处理器函数
sliderNavDisplayBtnClickHandler: {type: Function, default: () => {}},
})
/**
* 实现导航栏响应式
* @type {null}
*/
// logo 元素宽
let logoEleWidth = null
// 导航栏选项元素宽
let navItemsEleWidth = null
onMounted(() => {
// 获取 logo 元素宽
logoEleWidth = document.querySelector('.tail-top-nav .tail-top-nav-logo')?.clientWidth
// 获取导航栏选项元素宽
navItemsEleWidth = document.querySelector('.tail-top-nav .tail-top-nav-items')?.clientWidth
})
// 用于控制导航栏选项是否显示
const navItemsIsShow = ref(true)
// 顶部导航栏元素引用
const topNavRef = ref(null)
// 监听顶部导航栏元素内容和边框尺寸的变化
useResizeObserver(topNavRef, (entries) => {
const entry = entries[0]
// 获取顶部导航栏元素宽
const {width} = entry.contentRect
// 当顶部导航栏元素的宽度小于 logo + 导航栏选项元素宽度之和时,导航栏选项隐藏,否则导航栏选项显示
if (width <= logoEleWidth + navItemsEleWidth) navItemsIsShow.value = false
else navItemsIsShow.value = true
})
</script>
<template>
<!-- 小尾巴顶部导航组件 -->
<div class="tail-top-nav" ref="topNavRef">
<!-- 小尾巴顶部导航组件 logo -->
<div class="tail-top-nav-logo">
<slot name="topNavLogo"></slot>
</div>
<!-- 小尾巴顶部导航组件导航选项 -->
<div
v-if="navItemsIsShow"
class="tail-top-nav-items"
>
<slot name="topNavItems"></slot>
</div>
<!-- 小尾巴侧边导航栏展示按钮 -->
<div
v-else
class="tail-top-nav-slider-nav-display-btn"
@click="sliderNavDisplayBtnClickHandler"
>
<slot name="sliderNavDisplayBtn"></slot>
</div>
</div>
</template>
<style scoped lang="scss">
/*
* 小尾巴顶部导航组件
*/
.tail-top-nav {
box-sizing: border-box;
width: 100%;
padding: 0.5rem 1rem;
background-color: var(--tail-top-nav-bgc);
display: flex;
justify-content: space-between;
align-items: center;
/*
* 小尾巴顶部导航组件 logo
*/
.tail-top-nav-logo {
}
/*
* 小尾巴顶部导航组件导航选项
*/
.tail-top-nav-items {
display: flex;
justify-content: end;
align-items: center;
}
/*
* 小尾巴侧边导航栏展示按钮
*/
.tail-top-nav-slider-nav-display-btn {
height: 100%;
padding: 0.5rem;
cursor: pointer;
transition: all 0.5s;
display: flex;
justify-content: center;
align-items: center;
color: var(--tail-top-nav-font-color);
&:hover {
transform: scale(1.15);
}
}
}
</style>
组件使用说明
props 组件属性
组件属性 | 组件属性说明 | 组件属性值类型 | 组件属性默认值 |
---|---|---|---|
sliderNavDisplayBtnClickHandler | 小尾巴侧边导航栏组件展示按钮点击事件处理器函数,侧边导航栏组件显示按钮在顶部导航栏导航项收缩后才会显示,与侧边导航栏组件 https://www.yuque.com/u27599042/coding_star/vory2h7cv59sho1c 配合实现响应式 | Function | () => {} |
slot 插槽
插槽名称 | 插槽说明 |
---|---|
topNavLogo | 小尾巴顶部导航组件 logo,该插槽用户放置导航栏左部的 Logo |
sliderNavDisplayBtn | 小尾巴侧边导航栏展示按钮,该插槽用于放置侧边导航栏展示按钮 |