uniapp开发鸿蒙:Flex布局与基础组件实战

引入:从Hello World到实际布局

在上一篇文章中,我们已经完成了uniapp鸿蒙开发环境的搭建,创建了第一个项目。今天,我们将深入探讨uniapp在鸿蒙平台下的页面布局和基础组件使用,这是构建应用界面的核心基础。

uniapp的布局方式与鸿蒙原生语言ArkTs有所不同,但设计理念相似。所有布局方式都可以归纳为三种基本类型:横向、竖向和层叠,其他复杂布局都由这三种衍生而来。在uniapp中,我们主要通过view容器配合Flex布局来实现各种界面效果。

一、Flex布局基础

1.1 横向布局

横向布局是最常用的布局方式之一,通过设置flex-direction: row实现:

<view style="display: flex; flex-direction: row;">
  <view style="width: 100px; height: 100px; background-color: aqua;">组件1</view>
  <view style="width: 100px; height: 100px; background-color: bisque;">组件2</view>
</view>

1.2 纵向布局

纵向布局只需将flex-direction改为column

<view style="display: flex; flex-direction: column;">
  <view style="width: 100px; height: 100px; background-color: aqua;">组件1</view>
  <view style="width: 100px; height: 100px; background-color: bisque;">组件2</view>
</view>

1.3 层叠布局

uniapp没有直接提供类似ArkTs中Stack()的层叠布局容器,但可以通过position属性实现:

<view style="display: flex; flex-direction: column; position: relative;">
  <view style="width: 100px; height: 100px; background-color: aqua; position: absolute; top: 0;">组件1</view>
  <view style="width: 50px; height: 50px; background-color: bisque; position: absolute; z-index: 10; top: 0;">组件2</view>
</view>

关键点

  • 父容器需要设置position: relative
  • 子元素使用position: absolute进行绝对定位
  • 通过topleftrightbottom控制位置
  • 使用z-index控制层级关系

二、常用基础组件

2.1 view容器组件

view是uniapp中最基础的容器组件,相当于HTML中的div:

<view class="container">
  <view class="header">头部</view>
  <view class="content">内容区域</view>
  <view class="footer">底部</view>
</view>

2.2 text文本组件

text用于显示文本内容,支持丰富的样式设置:

<text style="font-size: 28rpx; color: #333; font-weight: bold;">这是一段文本</text>

2.3 image图片组件

image组件用于显示图片,支持多种加载模式:

<image src="/static/logo.png" mode="aspectFit" style="width: 200rpx; height: 200rpx;"></image>

mode属性说明

  • aspectFit:保持宽高比缩放,使图片的长边能完全显示出来
  • aspectFill:保持宽高比缩放,使图片的短边能完全显示出来
  • widthFix:宽度不变,高度自动变化,保持原图宽高比不变
  • heightFix:高度不变,宽度自动变化,保持原图宽高比不变

2.4 button按钮组件

button用于触发操作,支持多种样式和事件:

<button type="primary" size="default" @click="handleClick">点击按钮</button>

常用属性

  • type:按钮类型,可选值:default、primary、warn
  • size:按钮尺寸,可选值:default、mini
  • disabled:是否禁用
  • loading:是否显示加载中状态

三、rpx单位与响应式适配

3.1 rpx单位介绍

rpx(responsive pixel)是uniapp推荐的响应式单位,1rpx等于屏幕宽度的1/750。在不同设备上,rpx会自动转换为对应的像素值,实现自适应布局。

使用示例

.box {
  width: 750rpx;  /* 在750设计稿中,750rpx等于屏幕宽度 */
  height: 200rpx;
  font-size: 28rpx;
}

3.2 条件编译处理平台差异

uniapp支持条件编译,可以根据不同平台编写特定的样式代码:

/* 通用样式 */
.box {
  width: 100%;
  height: 200rpx;
}

/* 针对鸿蒙平台的样式 */
/* #ifdef HARMONYOS */
.box {
  background-color: #007AFF;
}
/* #endif */

/* 针对H5平台的样式 */
/* #ifdef H5 */
.box {
  background-color: #FF9500;
}
/* #endif */

条件编译语法

  • #ifdef:如果定义了某个平台,则编译
  • #ifndef:如果没有定义某个平台,则编译
  • #endif:结束条件编译

四、实战案例:构建首页布局

4.1 页面结构设计

下面是一个典型的首页布局结构:

<template>
  <view class="page">
    <!-- 头部导航栏 -->
    <view class="header">
      <text class="title">应用名称</text>
    </view>
    
    <!-- 内容区域 -->
    <view class="content">
      <!-- 轮播图 -->
      <swiper class="banner" indicator-dots="true" autoplay="true" interval="3000">
        <swiper-item>
          <image src="/static/banner1.jpg" mode="aspectFill"></image>
        </swiper-item>
        <swiper-item>
          <image src="/static/banner2.jpg" mode="aspectFill"></image>
        </swiper-item>
      </swiper>
      
      <!-- 功能导航 -->
      <view class="nav">
        <view class="nav-item" v-for="item in navList" :key="item.id">
          <image :src="item.icon" class="nav-icon"></image>
          <text class="nav-text">{{item.name}}</text>
        </view>
      </view>
      
      <!-- 商品列表 -->
      <view class="product-list">
        <view class="product-item" v-for="product in productList" :key="product.id">
          <image :src="product.image" class="product-image"></image>
          <view class="product-info">
            <text class="product-name">{{product.name}}</text>
            <text class="product-price">¥{{product.price}}</text>
          </view>
        </view>
      </view>
    </view>
    
    <!-- 底部标签栏 -->
    <view class="tabbar">
      <view class="tabbar-item" v-for="tab in tabbarList" :key="tab.id">
        <image :src="tab.icon" class="tabbar-icon"></image>
        <text class="tabbar-text">{{tab.name}}</text>
      </view>
    </view>
  </view>
</template>

4.2 样式实现

.page {
  display: flex;
  flex-direction: column;
  height: 100vh;
}

.header {
  height: 88rpx;
  background-color: #FFFFFF;
  display: flex;
  align-items: center;
  justify-content: center;
  border-bottom: 1rpx solid #EEEEEE;
}

.title {
  font-size: 36rpx;
  font-weight: bold;
  color: #333333;
}

.content {
  flex: 1;
  overflow-y: auto;
}

.banner {
  height: 300rpx;
}

.banner image {
  width: 100%;
  height: 100%;
}

.nav {
  display: flex;
  flex-wrap: wrap;
  padding: 30rpx;
  background-color: #FFFFFF;
  margin-top: 20rpx;
}

.nav-item {
  width: 25%;
  display: flex;
  flex-direction: column;
  align-items: center;
  margin-bottom: 20rpx;
}

.nav-icon {
  width: 80rpx;
  height: 80rpx;
}

.nav-text {
  font-size: 24rpx;
  color: #666666;
  margin-top: 10rpx;
}

.product-list {
  padding: 20rpx;
}

.product-item {
  display: flex;
  margin-bottom: 20rpx;
  background-color: #FFFFFF;
  border-radius: 10rpx;
  overflow: hidden;
}

.product-image {
  width: 200rpx;
  height: 200rpx;
}

.product-info {
  flex: 1;
  padding: 20rpx;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
}

.product-name {
  font-size: 28rpx;
  color: #333333;
}

.product-price {
  font-size: 32rpx;
  color: #FF6B00;
  font-weight: bold;
}

.tabbar {
  height: 100rpx;
  background-color: #FFFFFF;
  display: flex;
  border-top: 1rpx solid #EEEEEE;
}

.tabbar-item {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
}

.tabbar-icon {
  width: 44rpx;
  height: 44rpx;
}

.tabbar-text {
  font-size: 20rpx;
  color: #666666;
  margin-top: 6rpx;
}

4.3 数据绑定

export default {
  data() {
    return {
      navList: [
        { id: 1, name: '首页', icon: '/static/nav-home.png' },
        { id: 2, name: '分类', icon: '/static/nav-category.png' },
        { id: 3, name: '购物车', icon: '/static/nav-cart.png' },
        { id: 4, name: '我的', icon: '/static/nav-mine.png' }
      ],
      productList: [
        { id: 1, name: '商品名称1', price: 99.9, image: '/static/product1.jpg' },
        { id: 2, name: '商品名称2', price: 199.9, image: '/static/product2.jpg' },
        { id: 3, name: '商品名称3', price: 299.9, image: '/static/product3.jpg' }
      ],
      tabbarList: [
        { id: 1, name: '首页', icon: '/static/tab-home.png' },
        { id: 2, name: '分类', icon: '/static/tab-category.png' },
        { id: 3, name: '购物车', icon: '/static/tab-cart.png' },
        { id: 4, name: '我的', icon: '/static/tab-mine.png' }
      ]
    }
  }
}

五、布局技巧与最佳实践

5.1 Flex布局常用属性

主轴对齐方式

.container {
  justify-content: flex-start;    /* 左对齐 */
  justify-content: center;         /* 居中对齐 */
  justify-content: flex-end;        /* 右对齐 */
  justify-content: space-between;   /* 两端对齐,项目间间隔相等 */
  justify-content: space-around;   /* 每个项目两侧的间隔相等 */
}

交叉轴对齐方式

.container {
  align-items: flex-start;         /* 顶部对齐 */
  align-items: center;            /* 居中对齐 */
  align-items: flex-end;          /* 底部对齐 */
  align-items: stretch;           /* 拉伸填满容器高度 */
}

5.2 响应式布局处理

使用媒体查询

@media screen and (max-width: 750px) {
  .nav-item {
    width: 50%;
  }
}

@media screen and (min-width: 751px) {
  .nav-item {
    width: 25%;
  }
}

使用rpx适配

/* 在750设计稿中,750rpx等于屏幕宽度 */
.container {
  width: 750rpx;
  padding: 30rpx;
}

/* 在375设计稿中,375rpx等于屏幕宽度 */
.container {
  width: 375rpx;
  padding: 15rpx;
}

5.3 性能优化建议

  1. 避免过度嵌套:减少view容器的嵌套层级,提高渲染性能
  2. 使用条件编译:针对不同平台编写特定代码,避免不必要的代码执行
  3. 图片优化:使用合适的图片格式和尺寸,减少资源加载时间
  4. 样式复用:提取公共样式,减少代码冗余

总结

通过本篇文章的学习,我们掌握了uniapp在鸿蒙平台下的Flex布局和基础组件的使用方法。关键知识点包括:

  1. Flex布局:横向、纵向、层叠三种基本布局方式
  2. 基础组件:view、text、image、button等常用组件
  3. rpx单位:响应式布局的核心单位
  4. 条件编译:处理多平台差异的有效方法
  5. 实战案例:构建完整的首页布局

在实际开发中,建议多使用Flex布局,配合rpx单位实现响应式设计,同时通过条件编译处理平台差异。下一篇文章,我们将深入讲解页面路由与导航,实现多页面应用的跳转和数据传递。

Logo

作为“人工智能6S店”的官方数字引擎,为AI开发者与企业提供一个覆盖软硬件全栈、一站式门户。

更多推荐