uni-app:通过mod-nav-bar了解css的基本样式
发布时间 :
字数:2k
阅读 :
<!-- 逻辑与数据定义区:用于定义组件的 响应式数据、方法、生命周期、引入依赖 等逻辑 -->
<!-- <script setup> 是 Vue 3 引入的一种编译时语法糖,用于更简洁地编写组合式 API(Composition API)。 -->
<!-- 使用 <script setup> 语法糖后,你就不需要手动写 setup() 函数,
也不用写 export default {},更不用 return 数据 ——
Vue 编译器会自动帮你处理。 -->
<!-- setup 是 Vue 3 组件中用于定义响应式状态、方法、计算属性、监听器和生命周期钩子的“逻辑入口函数”。 -->
<script setup>
</script>
<!-- 视图结构(UI 模板):定义页面的 HTML 结构(在 uni-app 中是跨平台的标签)。 -->
<!-- <template> 是 Vue 的根模板容器,只能有一个根元素(这里就是 <view>)。 -->
<template>
<!-- uni-app 使用 <view> 而不是 <div>,因为:
<view> 是 uni-app 提供的跨平台组件,
在 H5 上编译为 div,在微信小程序上编译为 view,
在 App 上使用原生 View。 -->
<!-- 这里的 class 的值(如 "mod-nav-bar"、"fixed-wrap"、"status-bar" 等)
都是开发者自己定义的类名,
它们的作用就是 在 <style> 中通过 CSS 选择器来绑定样式。 -->
<!-- 这是一个 自定义导航栏(Custom Navigation Bar) 的典型结构,用于替代 uni-app 默认的原生导航栏。 -->
<!-- 最外层:.mod-nav-bar:整个自定义导航栏的容器。 -->
<view class="mod-nav-bar">
<!-- .fixed-wrap —— 真正固定在顶部的部分 -->
<view class="fixed-wrap">
<!-- .status-bar:占位 状态栏(Status Bar) 的高度(如 iPhone 的刘海区、安卓的时间/信号区)。 -->
<!-- 为什么需要?不同手机状态栏高度不同(iPhone 14 是 44px,安卓可能是 25px)。
uni-app 提供了 API 获取这个高度: const statusBarHeight = uni.getSystemInfoSync().statusBarHeight-->
<view class="status-bar"></view>
<!-- .title-bar 作用:模拟原生导航栏的“标题区域”(通常是 44px 或 88rpx 高)。 -->
<view class="title-bar">
<!-- 左侧区域:返回箭头 <、关闭图标、侧边栏按钮等 -->
<view class="arrow-wrap">
<!-- 这个 icon 来自 https://uniapp.dcloud.net.cn/component/uniui/uni-icons.html -->
<!-- 在这个项目的: .../uni_modules/uni-icons -->
<uni-icons class="icon" type="left" size="30"></uni-icons>
</view>
<!-- 中间区域:页面标题文字、Logo、搜索框等 -->
<view class="text-wrap">
标题
</view>
<!-- 右侧区域:分享、更多(⋯)、消息图标、发布按钮等 -->
<view class="menu-wrap"></view>
</view>
</view>
<!-- .block-wrap —— 占位块(关键!) -->
<!-- 在页面正常流中插入一个空白块,高度 = 状态栏 + 标题栏。 -->
<!-- 为什么需要?因为 .fixed-wrap 是 position: fixed(脱离文档流),
如果不加这个占位块,页面内容会从屏幕顶部开始渲染,被导航栏盖住! -->
<!-- 所以 .block-wrap 的高度必须等于 .fixed-wrap 的总高度,把页面内容“推下去”。 -->
<view class="block-wrap"></view>
</view>
</template>
<!-- 样式定义区:为当前组件定义 CSS 样式。 -->
<!-- lang="scss"是 <style> 标签的一个属性,表示当前样式块使用 SCSS 语法来编写 CSS。
默认情况下,<style> 里写的是普通 CSS。
但如果你加上 lang="scss",就可以使用 SCSS 预处理器的高级功能,
比如:嵌套规则、变量($primary-color)、混合(@mixin)、条件判断、循环等
-->
<!-- scoped 是 <style> 标签的一个属性(attribute),用于实现 CSS 样式作用域隔离。
默认情况下,一个 .vue 文件中的 CSS 会全局生效,可能影响其他页面。
加上 scoped 后,这些样式只作用于当前组件。
-->
<style lang="scss" scoped>
// 创建一个固定在顶部的自定义导航栏
// 最外层容器:.mod-nav-bar,整个导航栏模块的根容器。
.mod-nav-bar{
// 设置导航栏宽度
// uni-app 中,750rpx = 屏幕宽度(设计稿通常以 iPhone 6/7/8 的 375pt 为基准,1pt = 2rpx)。
width: 750rpx;
// 固定定位容器:.fixed-wrap
.fixed-wrap{
// position: fixed:让这个容器脱离文档流,固定在屏幕顶部(即使页面滚动也不会动)。
position: fixed;
// left: 0; top: 0; width: 100%:贴合屏幕左上角,横跨全屏。
left:0;
top:0;
width: 100%;
// 灰色背景
background: #ccc;
// 状态栏占位区:.status-bar
.status-bar{
//
width: 100%;
// 这是一个临时写死的值(实际应动态获取)。
height: 30rpx;
// 红色边框,仅用于调试(方便看到这个区域的位置和高度)。
border:1px solid red;
}
.title-bar{
// display: flex:启用 Flex 弹性布局(现代布局首选)。
// 关于弹性布局:https://www.linnote.space/2025/08/15/Flutter-05-flex/
// 主轴(main axis):默认是 水平方向(从左到右)
// 交叉轴(cross axis):与主轴垂直,默认是 垂直方向(从上到下)
display: flex;
width: 100%;
//text-align 的本意是:它是用于控制块级元素内部“行内内容”(inline content)的水平对齐方式。
//一旦你给一个容器设置了 display: flex,它的直接子元素就变成了“弹性项目(flex items)”,不再是普通的 inline 或 block 元素。
// 此时,text-align 只会影响子元素内部的文本,而不会影响子元素本身的位置。
// 它只会让 .arrow-wrap、.text-wrap、.menu-wrap 各自内部的文本居中(但这些子元素本身已经是块级,且内容通常只有一个字,所以看不出效果)。
// text-align: center;
// 让子元素左右对齐:第一个靠左,最后一个靠右,中间的自动居中。
// 正好对应:左(返回图标)— 中(标题)— 右(菜单)
// justify-content:控制主轴(水平)
justify-content:space-between;
// align-items:控制交叉轴(cross axis)对齐
// align-items 控制 Flex 容器中所有子元素在「垂直方向」上的对齐方式(当主轴是水平的时候)。
align-items: center;
// 标题栏高度(约 50px,比原生 44px 稍高,可自定义)。
height: 100rpx;
// 绿色边框,仅用于调试。
border:1px solid green;
// 左侧区域:.arrow-wrap
.arrow-wrap {
height: 100%;
width: 80rpx;
// flex-shrink:控制是否允许“缩小”
// flex-shrink: 0:禁止该元素在空间不足时被压缩(保持固定宽度)。
// flex-shrink: 1(默认)→ 允许缩小
/* 它的作用场景:
当 所有子元素的总宽度 > 容器宽度 时,浏览器会尝试“压缩”某些子元素来避免溢出。
如果某个子元素 flex-shrink: 1,它会被压缩(变窄)
如果 flex-shrink: 0,它死守原始宽度,不参与压缩*/
flex-shrink: 0;
display: flex;
// 让内部图标垂直居中
align-items: center;
}
// 中间区域:.text-wrap
.text-wrap {
/*
flex: 是 flex-grow, flex-shrink, flex-basis 三个属性的简写形式
关于这三个的意思,可以查看:https://www.linnote.space/2023/06/01/IntroductionOfHtmlCssJs/
三种写法
flex: 1; 最常见
flex: 1 1 0%; 等价于 flex: 1
flex: <flex-grow> <flex-shrink> <flex-basis>;
flex: 0 == flex: 0 1 auto == 不伸不缩,保持原始尺寸(常用于固定宽度元素)
flex: 1 == flex: 1 1 0% == 占满剩余空间(最常用!)
flex: auto == flex: 1 1 auto == 按内容宽度为基础,再分配剩余空间
flex: none == flex: 0 0 auto == 完全固定尺寸(等同于 width + flex-shrink:0)
flex: 2 == flex: 2 1 0% == 分配空间的比例是 flex:1 的 2 倍
*/
// flex: 1:表示“占据剩余所有空间”。
// 因为左右两侧是固定宽度,中间就会自动居中(配合父容器的 justify-content: space-between)。
// 文字内容会自然居中(如果需要强制居中,可加 text-align: center)。
flex: 1;
text-align: center; /* ✅ 这里才需要!让文字在中间区域居中 */
/*
.text-wrap 占据中间所有剩余空间(flex: 1)
它内部的“首页”文字通过 text-align: center 在这个宽区域内水平居中
左右两个区域固定宽度,整体看起来就是“左图标 - 居中标题 - 右图标”
*/
}
// 右侧区域:.menu-wrap
.menu-wrap {
height: 100%;
width: 80rpx;
flex-shrink: 0;
}
}
}
}
</style>