首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >第二章 小程序开发指南3-5

第二章 小程序开发指南3-5

原创
作者头像
抡大勺学小程序开发
修改2025-08-25 20:47:31
修改2025-08-25 20:47:31
1220
举报
2.4 场景应用

在本章会介绍小程序的基本开发流程,结合前面章节的知识,完全可以独立完成一个体验很完善的小程序。为了让开发者更加了解小程序开发,在本章中还会通过常见的一些应用场景介绍小程序API的一些细节以及开发的一些技巧和注意事项。

2.4.1 开发流程基本介绍

在启动开发之前,首先要对整个小程序整体的产品体验有一个清晰的规划和定义,一般会通过交互图或者手稿描绘小程序的界面交互和界面之间的跳转关系。如图4-1是一个管理文章留言小程序的交互图。

图4-1 文章留言管理的交互图

紧接着,优先完成WXML+WXSS还原设计稿,把界面涉及到的元素和视觉细节先调试完成。最后按照页面交互梳理出每个页面的data部分,填充WXML的模板语法,还有完成JS逻辑部分。

当然并不是要完全按照这样的开发流程来开发小程序,有些时候可能在产品交互体验还不明确的情况下,先完成JS逻辑层的一些模块的工作并做好测试。高效的开发流程有很多种方式,一般是根据整个团队的工作节奏来选择和开展,这一节讨论到的流程只是其中常见的开发流程。

2.4.2 基本的布局方法:Flex布局

如果之前接触过网页开发中的flexbox布局,基本上可以忽略本章节。但有一点需要注意的是,小程序要求兼容到iOS8以下版本,需要开启样式自动补全。开启样式自动补全是在“设置”—“项目设置”—勾选“上传代码时样式自动补全”,效果如图2-xx所示。

图4-2 开发者工具开启样式自动补全

在小程序开发中需要考虑各种尺寸终端设备上的适配。在传统网页开发,用的是Box盒模型,通过display:inline|block|inline-block、position、float来实现布局,缺乏灵活性且有些适配效果难以实现。比如像如图2-xx所示的这种常见的信息列表,要求内容高度不确定下保持垂直居中。

图4-3 常见的信息列表排版方式

这种情况下更建议使用flex布局。

在开始介绍flex之前,为了表述方便,约定以下术语:采用flex布局的元素,简称为“容器”,在代码示例中以container表示容器的类名。容器内的元素简称为“项目”,在代码示例中以item表示项目的类名,结构如图2-xx所示。

图4-4 container容器和item项目

2.4.2.1 基本概念

flex的概念最早是在2009年被提出的,目的是提供一种更灵活的布局模型,使容器能通过改变里面项目的高宽、顺序,来对可用空间实现最佳的填充,方便适配不同大小的内容区域。

在不固定高度信息的例子中,只需要在容器中设置以下两个属性即可实现内容不确定下的垂直居中。

.container {

  display: flex;

  flex-direction: column;

  justify-content: center;

}

flex不单是一个属性,还包含了一套新的属性集。属性集包括用于设置容器和用于设置项目的两部分。

设置容器的属性有:

(1)display:flex;

(2)flex-direction:row(默认值) | row-reverse | column | column-reverse

(3)flex-wrap:nowrap(默认值) | wrap | wrap-reverse

(4)justify-content:flex-start(默认值) | flex-end | center | space-between | space-around | space-evenly

(5)align-items:stretch(默认值) | center | flex-end | baseline | flex-start

(6)align-content:stretch(默认值) | flex-start | center | flex-end | space-between | space-around | space-evenly

设置项目的属性有:

(1)order:0(默认值) | <integer>

(2)flex-shrink:1(默认值) | <number>

(3)flex-grow:0(默认值) | <number>

(4)flex-basis:auto(默认值) | <length>

(5)flex:none | auto | @flex-grow @flex-shrink @flex-basis

(6)align-self:auto(默认值) | flex-start | flex-end |center | baseline| stretch

在开始介绍各个属性之前,需要先明确一个坐标轴。默认情况下,水平方向的是主轴(mainaxis),垂直方向的是交叉轴(crossaxis),如图2-xx所示。

图4-5 默认情况下的主轴与交叉轴

项目是在主轴上排列,排满后在交叉轴方向换行。需要注意的是,交叉轴垂直于主轴,它的方向取决于主轴方向,如图2-xx所示。

图4-6 项目是在主轴上排列,排满后在交叉轴方向换行

接下来的例子如无特殊声明,都以默认情况下的坐标轴为例。

2.4.2.2 容器属性

设置容器,用于统一管理容器内的项目布局,也就是管理项目的排列方式和对齐方式。

2.4.2.2.1 flex-direction属性:设置项目在容器里是横排放还是竖排放

通过设置坐标轴来设置项目的排列方向。

.container{

flex-direction: row(默认值) | row-reverse | column | column-reverse

}

row(默认值):主轴横向,方向为从左向右。项目沿主轴排列,从左到右排列。

row-reverse:row的反方向。主轴横向,方向为从右向左。项目沿主轴排列,从右到左排列。

column:主轴纵向,方向从上向下。项目沿主轴排列,从上到下排列。

column-reverse:column的反方向。主轴纵向,方向从下向上。项目沿主轴排列,从下到上排列。

运行效果如图2-xx所示。

图4-7 flex-direction

创建名称为flexDirection的小程序项目。

WXML示例代码如下:

<view>row</view>

<view class="container_row">

  <view style="background-color: red; height: 50px;">AAAAAA1</view>

  <view style="background-color: green;height: 60px;">BBBBBB2</view>

  <view style="background-color: blue;height: 70px;">CCCCCC3</view>

</view>

<view>row-reverse</view>

<view class="container_row_reverse">

  <view style="background-color: red; height: 50px;">AAAAAA1</view>

  <view style="background-color: green;height: 60px;">BBBBBB2</view>

  <view style="background-color: blue;height: 70px;">CCCCCC3</view>

</view>

<view>column</view>

<view class="container_column">

  <view style="background-color: red; height: 50px;">AAAAAA1</view>

  <view style="background-color: green;height: 60px;">BBBBBB2</view>

  <view style="background-color: blue;height: 70px;">CCCCCC3</view>

</view>

<view>column-reverse</view>

<view class="container_column_reverse">

  <view style="background-color: red; height: 50px;">AAAAAA1</view>

  <view style="background-color: green;height: 60px;">BBBBBB2</view>

  <view style="background-color: blue;height: 70px;">CCCCCC3</view>

</view>

WXSS示例代码如下:

.container_row {

  display: flex;

  flex-direction: row;

  background-color: #cccccc;

}

.container_row_reverse {

  display: flex;

  flex-direction: row-reverse;

  background-color: #cccccc;

}

.container_column {

  display: flex;

  flex-direction: column;

  background-color: #cccccc;

}

.container_column_reverse {

  display: flex;

  flex-direction: column-reverse;

  background-color: #cccccc;

}

程序运行效果如图2-xx所示。

图2-xx 运行效果

2.4.2.2.2 flex-wrap属性:设置行中的项目是否换行

设置是否允许项目多行排列,以及多行排列时换行的方向。

.container{

flex-wrap: nowrap(默认值) | wrap | wrap-reverse

}

nowrap(默认值):不换行。如果单行内容过多,则溢出容器。

wrap:容器单行容不下所有的项目时,换行排列。

wrap-reverse:容器单行容不下所有的项目时,换行排列。换行方向为wrap的反方向。

运行效果如图2-xx所示。

图4-8 flex-wrap

创建名称为flexWrap的小程序项目。

WXML示例代码如下:

<view>nowrap</view>

<view class="container_nowrap">

  <view style="background-color: red; height: 50px;">AAAAAA1</view>

  <view style="background-color: green;height: 60px;">BBBBBB2</view>

  <view style="background-color: blue;height: 70px;">CCCCCC3</view>

  <view style="background-color: red; height: 50px;">AAAAAA4</view>

  <view style="background-color: green;height: 60px;">BBBBBB5</view>

  <view style="background-color: blue;height: 70px;">CCCCCC6</view>

</view>

<view>wrap</view>

<view class="container_wrap">

  <view style="background-color: red; height: 50px;">AAAAAA1</view>

  <view style="background-color: green;height: 60px;">BBBBBB2</view>

  <view style="background-color: blue;height: 70px;">CCCCCC3</view>

  <view style="background-color: red; height: 50px;">AAAAAA4</view>

  <view style="background-color: green;height: 60px;">BBBBBB5</view>

  <view style="background-color: blue;height: 70px;">CCCCCC6</view>

</view>

<view>wrap-reverse</view>

<view class="container_wrap_reverse">

  <view style="background-color: red; height: 50px;">AAAAAA1</view>

  <view style="background-color: green;height: 60px;">BBBBBB2</view>

  <view style="background-color: blue;height: 70px;">CCCCCC3</view>

  <view style="background-color: red; height: 50px;">AAAAAA4</view>

  <view style="background-color: green;height: 60px;">BBBBBB5</view>

  <view style="background-color: blue;height: 70px;">CCCCCC6</view>

</view>

WXSS示例代码如下:

.container_nowrap {

  display: flex;

  flex-wrap: nowrap;

  background-color: #cccccc;

}

.container_wrap {

  display: flex;

  flex-wrap: wrap;

  background-color: #cccccc;

}

.container_wrap_reverse {

  display: flex;

  flex-wrap: wrap-reverse;

  background-color: #cccccc;

}

程序运行效果如图2-xx所示。

图2-xx 运行效果

2.4.2.2.3 justify-content属性:设置行中的项目在行中的水平对齐方式

设置项目在主轴方向上的对齐方式,以及分配项目之间及其周围多余的空间。

.container{

justify-content: flex-start(默认值) | center | flex-end | space-between | space-around | space-evenly

}

flex-start(默认值):项目对齐主轴起点,项目之间不留空隙。

center:项目在主轴上居中排列,项目之间不留空隙。主轴上第一个项目离主轴起点的距离等于最后一个项目离主轴终点的距离。

flex-end:项目对齐主轴终点,项目之间不留空隙。

space-between:项目之间的间距相等,第一个项目离主轴起点和最后一个项目离主轴终点距离为0。

space-around:与space-between相似。不同点为,第一个项目离主轴起点和最后一个项目离主轴终点距离为中间项目之间的间距的一半。

space-evenly:项目之间的间距、第一个项目离主轴起点和最后一个项目离主轴终点的距离等于项目之间的间距。

运行效果如图2-xx所示。

IMG_256
IMG_256

图4-9 justify-content

创建名称为justifyContent的小程序项目。

WXML示例代码如下:

<view>flex-start</view>

<view class="container_flex_start">

  <view style="background-color: red; height: 50px;">AAAAAA1</view>

  <view style="background-color: green;height: 60px;">BBBBBB2</view>

  <view style="background-color: blue;height: 70px;">CCCCCC3</view>

  <view style="background-color: red; height: 50px;">AAAAAA4</view>

  <view style="background-color: green;height: 60px;">BBBBBB5</view>

  <view style="background-color: blue;height: 70px;">CCCCCC6</view>

</view>

<view>center</view>

<view class="container_center">

  <view style="background-color: red; height: 50px;">AAAAAA1</view>

  <view style="background-color: green;height: 60px;">BBBBBB2</view>

  <view style="background-color: blue;height: 70px;">CCCCCC3</view>

</view>

<view>flex-end</view>

<view class="container_flex_end">

  <view style="background-color: red; height: 50px;">AAAAAA1</view>

  <view style="background-color: green;height: 60px;">BBBBBB2</view>

  <view style="background-color: blue;height: 70px;">CCCCCC3</view>

  <view style="background-color: red; height: 50px;">AAAAAA4</view>

  <view style="background-color: green;height: 60px;">BBBBBB5</view>

  <view style="background-color: blue;height: 70px;">CCCCCC6</view>

</view>

<view>space-between</view>

<view class="container_space_between">

  <view style="background-color: red; height: 50px;">AAAAAA1</view>

  <view style="background-color: green;height: 60px;">BBBBBB2</view>

  <view style="background-color: blue;height: 70px;">CCCCCC3</view>

</view>

<view>space-around</view>

<view class="container_space_around">

  <view style="background-color: red; height: 50px;">AAAAAA1</view>

  <view style="background-color: green;height: 60px;">BBBBBB2</view>

  <view style="background-color: blue;height: 70px;">CCCCCC3</view>

</view>

<view>space-evenly</view>

<view class="container_space_evenly">

  <view style="background-color: red; height: 50px;">AAAAAA1</view>

  <view style="background-color: green;height: 60px;">BBBBBB2</view>

  <view style="background-color: blue;height: 70px;">CCCCCC3</view>

</view>

WXSS示例代码如下:

.container_flex_start {

  display: flex;

  justify-content: flex-start;

  background-color: #cccccc;

}

.container_center {

  display: flex;

  justify-content: center;

  background-color: #cccccc;

}

.container_flex_end {

  display: flex;

  justify-content: flex-end;

  background-color: #cccccc;

}

.container_space_between {

  display: flex;

  justify-content: space-between;

  background-color: #cccccc;

}

.container_space_around {

  display: flex;

  justify-content: space-around;

  background-color: #cccccc;

}

.container_space_evenly {

  display: flex;

  justify-content: space-evenly;

  background-color: #cccccc;

}

程序运行效果如图2-xx所示。

图2-xx 运行效果

2.4.2.2.4 align-items属性:设置行中的项目在行中的垂直对齐方式

设置项目在行中的对齐方式。

.container{

align-items:stretch(默认值) | flex-start | center | flex-end | baseline

}

stretch(默认值):项目拉伸至填满行高。

flex-start:项目顶部与行起点对齐。

center:项目在行中居中对齐。

flex-end:项目底部与行终点对齐。

baseline:项目的第一行文字的基线对齐。。

运行效果如图2-xx所示。

IMG_256
IMG_256
IMG_256
IMG_256

图4-10 align-items

创建名称为alignItems的小程序项目。

WXML示例代码如下:

<view>stretch</view>

<view class="container_stretch">

  <view style="background-color: red;">AAAAAA1</view>

  <view style="background-color: green;">BBBBBB2</view>

  <view style="background-color: blue;">CCCCCC3</view>

  <view style="background-color: red;">AAAAAA1</view>

  <view style="background-color: green;">BBBBBB2</view>

  <view style="background-color: blue;">CCCCCC3</view>

</view>

<view>flex-start</view>

<view class="container_flex_start">

  <view style="background-color: red; height: 50px;">AAAAAA1</view>

  <view style="background-color: green;height: 60px;">BBBBBB2</view>

  <view style="background-color: blue;height: 70px;">CCCCCC3</view>

  <view style="background-color: red; height: 50px;">AAAAAA1</view>

  <view style="background-color: green;height: 60px;">BBBBBB2</view>

  <view style="background-color: blue;height: 70px;">CCCCCC3</view>

</view>

<view>center</view>

<view class="container_center">

  <view style="background-color: red; height: 50px;">AAAAAA1</view>

  <view style="background-color: green;height: 60px;">BBBBBB2</view>

  <view style="background-color: blue;height: 70px;">CCCCCC3</view>

  <view style="background-color: red; height: 50px;">AAAAAA1</view>

  <view style="background-color: green;height: 60px;">BBBBBB2</view>

  <view style="background-color: blue;height: 70px;">CCCCCC3</view>

</view>

<view>flex-end</view>

<view class="container_flex_end">

  <view style="background-color: red; height: 50px;">AAAAAA1</view>

  <view style="background-color: green;height: 60px;">BBBBBB2</view>

  <view style="background-color: blue;height: 70px;">CCCCCC3</view>

  <view style="background-color: red; height: 50px;">AAAAAA1</view>

  <view style="background-color: green;height: 60px;">BBBBBB2</view>

  <view style="background-color: blue;height: 70px;">CCCCCC3</view>

</view>

<view>baseline</view>

<view class="container_baseline">

  <view style="background-color: red; height: 50px; padding-top: 30px;">AAAAAA1</view>

  <view style="background-color: green;height: 60px;">BBBBBB2</view>

  <view style="background-color: blue;height: 70px;padding-top: 30px;">CCCCCC3</view>

  <view style="background-color: red; height: 50px; padding-top: 30px;">AAAAAA1</view>

  <view style="background-color: green;height: 60px;">BBBBBB2</view>

  <view style="background-color: blue;height: 70px;padding-top: 30px;">CCCCCC3</view>

</view>

WXSS示例代码如下:

.container_stretch {

  display: flex;

  flex-wrap: wrap;

  align-items: stretch;

  height: 250px;

  background-color: #cccccc;

}

.container_flex_start {

  display: flex;

  flex-wrap: wrap;

  align-items: flex-start;

  height: 250px;

  background-color: #cccccc;

}

.container_center {

  display: flex;

  flex-wrap: wrap;

  align-items: center;

  height: 250px;

  background-color: #cccccc;

}

.container_flex_end {

  display: flex;

  flex-wrap: wrap;

  align-items: flex-end;

  height: 250px;

  background-color: #cccccc;

}

.container_baseline {

  display: flex;

  flex-wrap: wrap;

  align-items: baseline;

  height: 250px;

  background-color: #cccccc;

}

程序运行效果如图2-xx所示。

图2-xx 运行效果

程序运行效果如图2-xx所示。

图2-xx 运行效果

程序运行效果如图2-xx所示。

图2-xx 运行效果

2.4.2.2.5 align-content属性:设置容器里所有的项目在容器中的垂直对齐方式

多行排列时,设置行在交叉轴方向上的对齐方式,以及分配行之间及其周围多余的空间。

.container{

align-content: stretch(默认值) | flex-start | center | flex-end | space-between |space-around | space-evenly

}

stretch(默认值):当未设置项目的尺寸,将各行中的项目拉伸至填满交叉轴。当设置了项目尺寸,项目尺寸不变,项目行拉伸至填满交叉轴。

flex-start:首行在交叉轴起点开始排列,行之间不留间距。

center:行在交叉轴中点排列,行之间不留间距,首行离交叉轴起点和尾行离交叉轴终点的距离相等。

flex-end:尾行在交叉轴终点开始排列,行之间不留间距。

space-between:行与行的间距相等,首行离交叉轴起点和尾行离交叉轴终点的距离为0。

space-around:行与行的间距相等,首行离交叉轴起点和尾行离交叉轴终点的距离为行与行之间的间距的一半。

space-evenly:行之间的间距、以及首行离交叉轴起点和尾行离交叉轴终点的距离相等。

运行效果如图2-xx所示。

IMG_256
IMG_256
IMG_256
IMG_256
IMG_256
IMG_256

图4-11 align-content

创建名称为alignContent的小程序项目。

WXML示例代码如下:

<view>stretch_nosize</view>

<view class="container_stretch_nosize">

  <view style="background-color: red;">AAAAAA1</view>

  <view style="background-color: green;">BBBBBB2</view>

  <view style="background-color: blue;">CCCCCC3</view>

  <view style="background-color: red;">AAAAAA1</view>

  <view style="background-color: green;">BBBBBB2</view>

  <view style="background-color: blue;">CCCCCC3</view>

</view>

<view>stretch_hassize</view>

<view class="container_stretch_hassize">

  <view style="background-color: red; width: 80px;">AAAAAA1</view>

  <view style="background-color: green; width: 80px;">BBBBBB2</view>

  <view style="background-color: blue; width: 80px;">CCCCCC3</view>

  <view style="background-color: red; width: 80px;">AAAAAA1</view>

  <view style="background-color: green; width: 80px;">BBBBBB2</view>

  <view style="background-color: blue; width: 80px;">CCCCCC3</view>

</view>

<view>flex-start</view>

<view class="container_flex_start">

  <view style="background-color: red;">AAAAAA1</view>

  <view style="background-color: green;">BBBBBB2</view>

  <view style="background-color: blue;">CCCCCC3</view>

  <view style="background-color: red;">AAAAAA1</view>

  <view style="background-color: green;">BBBBBB2</view>

  <view style="background-color: blue;">CCCCCC3</view>

</view>

<view>center</view>

<view class="container_center">

  <view style="background-color: red;">AAAAAA1</view>

  <view style="background-color: green;">BBBBBB2</view>

  <view style="background-color: blue;">CCCCCC3</view>

  <view style="background-color: red;">AAAAAA1</view>

  <view style="background-color: green;">BBBBBB2</view>

  <view style="background-color: blue;">CCCCCC3</view>

</view>

<view>flex-end</view>

<view class="container_flex_end">

  <view style="background-color: red;">AAAAAA1</view>

  <view style="background-color: green;">BBBBBB2</view>

  <view style="background-color: blue;">CCCCCC3</view>

  <view style="background-color: red;">AAAAAA1</view>

  <view style="background-color: green;">BBBBBB2</view>

  <view style="background-color: blue;">CCCCCC3</view>

</view>

<view>space-between</view>

<view class="container_space_between">

  <view style="background-color: red; width: 100px;">AAAAAA1</view>

  <view style="background-color: green; width: 100px;">BBBBBB2</view>

  <view style="background-color: blue; width: 100px;">CCCCCC3</view>

  <view style="background-color: red; width: 100px;">AAAAAA4</view>

  <view style="background-color: green; width: 100px;">BBBBBB5</view>

  <view style="background-color: blue; width: 100px;">CCCCCC6</view>

  <view style="background-color: red; width: 100px;">AAAAAA7</view>

  <view style="background-color: green; width: 100px;">BBBBBB8</view>

  <view style="background-color: blue; width: 100px;">CCCCCC9</view>

</view>

<view>space-around</view>

<view class="container_space_around">

  <view style="background-color: red; width: 100px;">AAAAAA1</view>

  <view style="background-color: green; width: 100px;">BBBBBB2</view>

  <view style="background-color: blue; width: 100px;">CCCCCC3</view>

  <view style="background-color: red; width: 100px;">AAAAAA4</view>

  <view style="background-color: green; width: 100px;">BBBBBB5</view>

  <view style="background-color: blue; width: 100px;">CCCCCC6</view>

  <view style="background-color: red; width: 100px;">AAAAAA7</view>

  <view style="background-color: green; width: 100px;">BBBBBB8</view>

  <view style="background-color: blue; width: 100px;">CCCCCC9</view>

</view>

<view>space-evenly</view>

<view class="container_space_evenly">

  <view style="background-color: red; width: 100px;">AAAAAA1</view>

  <view style="background-color: green; width: 100px;">BBBBBB2</view>

  <view style="background-color: blue; width: 100px;">CCCCCC3</view>

  <view style="background-color: red; width: 100px;">AAAAAA4</view>

  <view style="background-color: green; width: 100px;">BBBBBB5</view>

  <view style="background-color: blue; width: 100px;">CCCCCC6</view>

  <view style="background-color: red; width: 100px;">AAAAAA7</view>

  <view style="background-color: green; width: 100px;">BBBBBB8</view>

  <view style="background-color: blue; width: 100px;">CCCCCC9</view>

</view>

WXSS示例代码如下:

.container_stretch_nosize {

  display: flex;

  flex-wrap: wrap;

  align-content: stretch;

  height: 250px;

  background-color: #cccccc;

}

.container_stretch_hassize {

  display: flex;

  flex-wrap: wrap;

  align-content: stretch;

  height: 250px;

  background-color: #cccccc;

}

.container_flex_start {

  display: flex;

  flex-wrap: wrap;

  align-content: flex-start;

  height: 250px;

  background-color: #cccccc;

}

.container_center {

  display: flex;

  flex-wrap: wrap;

  align-content: center;

  height: 250px;

  background-color: #cccccc;

}

.container_flex_end {

  display: flex;

  flex-wrap: wrap;

  align-content: flex-end;

  height: 250px;

  background-color: #cccccc;

}

.container_space_between {

  display: flex;

  flex-wrap: wrap;

  align-content: space-between;

  height: 250px;

  background-color: #cccccc;

}

.container_space_around {

  display: flex;

  flex-wrap: wrap;

  align-content: space-around;

  height: 150px;

  background-color: #cccccc;

}

.container_space_evenly {

  display: flex;

  flex-wrap: wrap;

  align-content: space-evenly;

  height: 150px;

  background-color: #cccccc;

}

程序运行效果如图2-xx所示。

图2-xx 运行效果

程序运行效果如图2-xx所示。

图2-xx 运行效果

程序运行效果如图2-xx所示。

图2-xx 运行效果

2.4.2.3 项目属性

设置项目,用于设置项目的尺寸、位置,以及对项目的对齐方式做特殊的设置。

2.4.2.3.1 order属性:排序优先级

设置项目沿主轴方向上的排列顺序,数值越小,排列越靠前。属性值为整数。

.item{

order: 0(默认值) | <integer>

}

运行效果如图2-xx所示。

图4-12 order

创建名称为order的小程序项目。

WXML示例代码如下:

<view class="container_my">

  <view style="background-color: red; height: 50px;" class="item1">AAAAAA1</view>

  <view style="background-color: green;height: 60px;" class="item2">BBBBBB2</view>

  <view style="background-color: blue;height: 90px;" class="item3">CCCCCC3</view>

  <view style="background-color:pink;height: 80px;" class="item4">DDDDDD4</view>

</view>

WXSS示例代码如下:

.container_my {

  display: flex;

  background-color: #cccccc;

}

.item2 {

  order: 0

}

.item1 {

  order: 1

}

.item3 {

  order: 4

}

.item4 {

  order: 3

}

程序运行效果如图2-xx所示。

图2-xx 运行效果

2.4.2.3.2 flex-shrink属性:压缩项目

当项目在主轴方向上溢出时,通过设置项目收缩因子来压缩项目以适应容器的宽度。flex-shrink属性值为项目的收缩因子,取值为非负数,示例代码如下:

.item{

flex-shrink: 1(默认值) | <number>

}

为了加深理解,举个例子。

一个宽度为400px的容器,示例代码如下:

.container{

display: flex;

width: 400px; // 容器宽度为400px

}

里面三个项目的width分别为120px,150px,180px。然后对项目1和项目2设置flex-shrink值为2和3,示例代码如下:

.item1{

width: 120px;

flex-shrink: 2;

}

.item2{

width: 150px;

flex-shrink: 3;

}

.item3{ // 项目3未设置flex-shrink,默认flex-shrink值为1

width: 180px;

}

在这个例子中,项目溢出400 - (120 + 150 + 180) = -50px,溢出50px。计算压缩总权重为各个项目的宽度乘以flex-shrink的总和,这个例子压缩总权重为120 * 2 + 150 * 3+ 180 * 1 = 870。各个项目压缩空间大小为总溢出空间乘以项目宽度乘以flex-shrink除以压缩总权重:

item1的最终宽度为:120 - 50 * 120 * 2 / 870 ≈ 106px

item2的最终宽度为:150 - 50 * 150 * 3 / 870 ≈ 124px

item3的最终宽度为:180 - 50 * 180 * 1 / 870 ≈ 169px

其中计算的值如果为小数,则向下取整。

运行效果如图2-xx所示。

图4-13 flex-shrink

创建名称为flexShrink的小程序项目。

WXML示例代码如下:

<view class="container_my">

  <view id="aView" style="background-color: red; width:120px; flex-shrink: 2;">{{aViewWidth}}</view>

  <view id="bView" style="background-color: green;width: 150px; flex-shrink: 3;">{{bViewWidth}}</view>

  <view id="cView" style="background-color: blue;width:180px; flex-shrink: 1;">{{cViewWidth}}</view>

</view>

WXSS示例代码如下:

.container_my {

  display: flex;

  background-color: #cccccc;

}

JS示例代码如下:

Page({

  data: {

    containerWidth: 400,

    itemsWidthAndFlexShrink: [

      { width: 120, flexShrink: 2 },

      { width: 150, flexShrink: 3 },

      { width: 180, flexShrink: 1 },

    ],

    aViewWidth: 0,

    bViewWidth: 0,

    cViewWidth: 0,

  },

  onReady: function () {

    this.calculateFinalWidths();

    this.showViewWidth();

  },

  calculateFinalWidths: function () {

    // 1. 复制原始数据,防止原始数组被更改

    let newItems = [];

    for (let i = 0; i < this.data.itemsWidthAndFlexShrink.length; i++) {

      newItems.push({

        width: this.data.itemsWidthAndFlexShrink[i].width,

        flexShrink: this.data.itemsWidthAndFlexShrink[i].flexShrink

      });

    }

    // 容器宽度

    let containerWidth = this.data.containerWidth;

    // item个数

    let itemCount = newItems.length;

    // 2. 计算全部item的宽度总和

    let itemsTotalInitialWidth = 0;

    for (let i = 0; i < itemCount; i++) {

      itemsTotalInitialWidth += newItems[i].width;

    }

    // 3. 计算需要压缩的总空间,也就是多出来的宽度

    //    如果不需要压缩,直接返回(item总宽度小于容器的宽度)

    let overflowWidth = itemsTotalInitialWidth - containerWidth;

    if (overflowWidth <= 0) {

      // 说明item的宽度总和比容器宽度小,所以根本不需要压缩,直接打印原始的item宽度就可以

      this.printResults(newItems);

      return;

    }

    // 4. 核心算法:分步压缩

    // 4.1 先计算不可压缩元素的总宽度(flexShrink=0的元素)

    let noShrinkTotalWidth = 0;

    for (let i = 0; i < itemCount; i++) {

      if (newItems[i].flexShrink === 0) {

        noShrinkTotalWidth += newItems[i].width;

      }

    }

    // 4.2 计算可压缩元素可用的总空间

    let availableSpaceWidth = containerWidth - noShrinkTotalWidth;

    if (availableSpaceWidth < 0) {

      // 极端情况:固定元素已超过容器

      availableSpaceWidth = 0;

    }

    // 4.3 收集可压缩元素(flexShrink>0)

    let shrinkableItems = [];

    for (let i = 0; i < itemCount; i++) {

      if (newItems[i].flexShrink > 0) {

        shrinkableItems.push(newItems[i]);

      }

    }

    // 4.4 计算可压缩元素的总初始宽度

    let shrinkableTotalWidth = 0;

    for (let i = 0; i < shrinkableItems.length; i++) {

      shrinkableTotalWidth += shrinkableItems[i].width;

    }

    // 4.5 如果可压缩元素总宽度 <= 可用空间,无需压缩

    if (shrinkableTotalWidth <= availableSpaceWidth) {

      this.printResults(newItems);

      return;

    }

    // 4.6 计算需要压缩的总量(可压缩元素超出可用空间的部分)

    let needShrinkTotalWidth = shrinkableTotalWidth - availableSpaceWidth;

    // 4.7 分步压缩(解决精度问题的关键)

    while (needShrinkTotalWidth > 0) {

      // 计算当前可压缩元素的总权重(排除已压缩到0的)

      let totalWeight = 0;

      let activeItems = []; // 当前还能压缩的元素(宽度>0)

      for (let i = 0; i < shrinkableItems.length; i++) {

        if (shrinkableItems[i].width > 0) {

          activeItems.push(shrinkableItems[i]);

          totalWeight += shrinkableItems[i].width * shrinkableItems[i].flexShrink;

        }

      }

      if (activeItems.length === 0) break; // 无可压缩元素

      // 按权重分配当前需要压缩的量

      let currentShrink = needShrinkTotalWidth;

      for (let i = 0; i < activeItems.length; i++) {

        let item = activeItems[i];

        let itemWeight = item.width * item.flexShrink;

        let ratio = itemWeight / totalWeight;

        // 计算应压缩的量

        let itemShrink = currentShrink * ratio;

        // 限制最大压缩量(不能超过当前宽度)

        if (itemShrink > item.width) {

          itemShrink = item.width;

        }

        // 执行压缩

        item.width -= itemShrink;

        needShrinkTotalWidth -= itemShrink;

        // 如果压缩到0,跳出本轮循环,重新计算权重

        if (item.width === 0) {

          break;

        }

      }

    }

    // 5. 确保宽度非负

    for (let i = 0; i < itemCount; i++) {

      if (newItems[i].width < 0) {

        newItems[i].width = 0;

      }

    }

    // 6. 输出结果

    this.printResults(newItems);

  },

  printResults: function (items) {

    for (let i = 0; i < items.length; i++) {

      console.log("item " + (i + 1) + " width:" + items[i].width);

    }

  },

  showViewWidth: function () {

    let viewArray = ["aView", "bView", "cView"];

    for (let i = 0; i < viewArray.length; i++) {

      let eachIdValue = viewArray[i];

      // 1. 创建查询实例

      let query = wx.createSelectorQuery();

      // 2. 选择元素并指定获取的属性

      query.select('#' + eachIdValue).boundingClientRect();

      // 3. 执行查询

      query.exec((res) => {

        // res 是包含查询结果的数组

        const rect = res[0];

        console.log('元素宽度:', rect.width);

        console.log('元素高度:', rect.height);

        console.log('元素位置:', rect.left, rect.top);

        console.log("");

        let key = eachIdValue + "Width";

        let value = parseInt("" + rect.width);

        this.setData({ [key]: value });

      });

    }

  }

})

程序运行效果如图2-xx所示。

图2-xx 运行效果

需要注意一点,当项目的压缩因子相加小于1时,参与计算的溢出空间不等于完整的溢出空间。在上面例子的基础上,改变各个项目的flex-shrink。

.container{

display: flex;

width: 400px; // 容器宽度为400px

}

.item1{

width: 120px;

flex-shrink: 0.1;

}

.item2{

width: 150px;

flex-shrink: 0.2;

}

.item3{

width: 180px;

flex-shrink: 0.3;

}

总权重为:120 * 0.1 + 150 * 0.2 + 180 * 0.3 = 96。参与计算的溢出空间不再是50px,而是50 * (0.1 + 0.2 + 0.3) / 1 =30:

item1的最终宽度为:120 - 30 * 120 * 0.1 / 96 ≈ 116px

item2的最终宽度为:150 - 30 * 150 * 0.2 / 96 ≈ 140px

item3的最终宽度为:180 - 30 * 180 * 0.3 / 96 ≈ 163px

更改WXML示例代码如下:

<view class="container_my">

  <view id="aView" style="background-color: red; width:120px; flex-shrink: 0.1;">{{aViewWidth}}</view>

  <view id="bView" style="background-color: green;width: 150px; flex-shrink: 0.2;">{{bViewWidth}}</view>

  <view id="cView" style="background-color: blue;width:180px; flex-shrink: 0.3;">{{cViewWidth}}</view>

</view>

更改JS示例代码如下:

    itemsWidthAndFlexShrink: [

      { width: 120, flexShrink: 0.1 },

      { width: 150, flexShrink: 0.2 },

      { width: 180, flexShrink: 0.3 },

    ]

程序运行效果如图2-xx所示。

图2-xx 运行效果

2.4.2.3.3 flex-grow属性:扩张项目

当项目在主轴方向上还有剩余空间时,通过设置项目扩张因子进行剩余空间的分配。flex-grow属性值为项目的扩张因子,取值为非负数,示例代码如下:

.item{

flex-grow: 0(默认值) | <number>

}

为了加深理解,举个例子。

一个宽度为400px的容器,里面的三个项目width分别为80px,120px,140px。分别对这项目1和项目2设置flex-grow值为3和1。

.container{

display: flex;

width: 400px; // 容器宽度为400px

}

.item1{

width: 80px;

flex-grow: 3;

}

.item2{

width: 120px;

flex-grow: 1;

}

.item3{// 项目3未设置flex-grow,默认flex-grow值为0

width: 140px;

}

在这个例子中,容器的剩余空间为 400 - (80 + 120 + 140) = 60px。剩余空间按 60 / (3 + 1 + 0) = 15px进行分配:

item1的最终宽度为:80+ (15 * 3) = 125px

item2的最终宽度为:120 + (15 * 1) = 135px

item3的最终宽度为:140 + (15 * 0) =140px

运行效果如图2-xx所示。

图4-14 flex-grow

创建名称为flexGrow的小程序项目。

WXML示例代码如下:

<view class="container_my">

  <view id="aView" style="background-color: red; width:80px; flex-grow: 3;">{{aViewWidth}}</view>

  <view id="bView" style="background-color: green;width: 120px; flex-grow: 1;">{{bViewWidth}}</view>

  <view id="cView" style="background-color: blue;width:140px; flex-grow: 0;">{{cViewWidth}}</view>

</view>

WXSS示例代码如下:

.container_my {

  display: flex;

  background-color: #cccccc;

}

JS示例代码如下:

Page({

  data: {

    containerWidth: 400,

    itemsWidthAndFlexGrow: [

      { width: 80, flexGrow: 3 },

      { width: 120, flexGrow: 1 },

      { width: 140, flexGrow: 0 },

    ],

    aViewWidth: 0,

    bViewWidth: 0,

    cViewWidth: 0,

  },

  onReady: function () {

    this.calculateFinalWidths();

    this.showViewWidth();

  },

  calculateFinalWidths: function () {

    // 1. 复制原始数据,防止修改原数组

    let newItems = [];

    for (let i = 0; i < this.data.itemsWidthAndFlexGrow.length; i++) {

      newItems.push({

        width: this.data.itemsWidthAndFlexGrow[i].width,

        flexGrow: this.data.itemsWidthAndFlexGrow[i].flexGrow

      });

    }

    // 容器宽度

    const containerWidth = this.data.containerWidth;

    // item个数

    let itemCount = newItems.length;

    // 2. 计算全部item的宽度总和

    let itemsTotalInitialWidth = 0;

    for (let i = 0; i < itemCount; i++) {

      itemsTotalInitialWidth += newItems[i].width;

    }

    // 3. 计算剩余空间(容器宽度 - 初始总宽度)

    //    如果没有剩余空间(<=0),直接使用初始宽度

    const remainingSpace = containerWidth - itemsTotalInitialWidth;

    if (remainingSpace <= 0) {

      this.printResults(newItems);

      return;

    }

    // 4. 收集可扩展元素(flexGrow > 0的元素)

    let growableItems = [];

    for (let i = 0; i < newItems.length; i++) {

      if (newItems[i].flexGrow > 0) {

        growableItems.push(newItems[i]);

      }

    }

    // 计算可扩展元素的总权重(flexGrow之和)

    let totalGrowWeight = 0;

    for (let i = 0; i < growableItems.length; i++) {

      totalGrowWeight += growableItems[i].flexGrow;

    }

    // 5. 如果没有可扩展元素或总权重为0,剩余空间不分配

    if (totalGrowWeight <= 0) {

      this.printResults(newItems);

      return;

    }

    // 6. 按权重分配剩余空间

    //    计算每个权重单位可分配的空间

    const spacePerWeight = remainingSpace / totalGrowWeight;

    // 为每个可扩展元素分配空间

    for (let i = 0; i < growableItems.length; i++) {

      let item = growableItems[i];

      // 计算当前元素应分配的额外空间

      let additionalSpace = item.flexGrow * spacePerWeight;

      // 累加额外空间到初始宽度

      item.width += additionalSpace;

    }

    // 7. 输出结果

    this.printResults(newItems);

  },

  printResults: function (items) {

    for (let i = 0; i < items.length; i++) {

      console.log("item " + (i + 1) + " width:" + items[i].width);

    }

  },

  showViewWidth: function () {

    let viewArray = ["aView", "bView", "cView"];

    for (let i = 0; i < viewArray.length; i++) {

      let eachIdValue = viewArray[i];

      // 创建查询实例

      let query = wx.createSelectorQuery();

      // 选择元素并指定获取的属性

      query.select('#' + eachIdValue).boundingClientRect();

      // 执行查询

      query.exec((res) => {

        // res 是包含查询结果的数组

        const rect = res[0];

        console.log('元素宽度:', rect.width);

        console.log('元素高度:', rect.height);

        console.log('元素位置:', rect.left, rect.top);

        console.log("");

        let key = eachIdValue + "Width";

        let value = parseInt("" + rect.width);

        this.setData({ [key]: value });

      });

    }

  }

})

程序运行效果如图2-xx所示。

图2-xx 运行效果

需要注意一点,当项目的扩张因子相加小于1时,剩余空间按除以1进行分配。在上面例子的基础上,改变各个项目的flex-grow。

.container{

display: flex;

width: 400px; // 容器宽度为400px

}

.item1{

width: 50px;

flex-grow: 0.1;

}

.item2{

width: 80px;

flex-grow: 0.3;

}

.item3{

width: 110px;

flex-grow: 0.2;

}

在这个例子中,容器的剩余空间为400 - (50 + 80 + 110) = 160px。由于项目的flex-grow相加0.1 + 0.3 + 0.2 = 0.6小于1,剩余空间按160 / 1 = 160px划分。例子中的项目宽度分别为:

item1的最终宽度为:50 + (160 * 0.1) = 66px

item2的最终宽度为:80 + (160 * 0.3) = 128px

item3的最终宽度为:110 + (160 * 0.2) = 142px

更改WXML示例代码如下:

<view class="container_my">

  <view id="aView" style="background-color: red; width:50px; flex-grow: 0.1;">{{aViewWidth}}</view>

  <view id="bView" style="background-color: green;width: 80px; flex-grow: 0.3;">{{bViewWidth}}</view>

  <view id="cView" style="background-color: blue;width:110px; flex-grow: 0.2;">{{cViewWidth}}</view>

</view>

更改JS示例代码如下:

    itemsWidthAndFlexGrow: [

      { width: 50, flexGrow: 0.1 },

      { width: 80, flexGrow: 0.3 },

      { width: 110, flexGrow: 0.2 },

    ]

程序运行效果如图2-xx所示。

图2-xx 运行效果

2.4.2.3.4 flex-basis属性:代替width或者height

当容器设置flex-direction为row或row-reverse时,flex-basis和width同时存在,flex-basis优先级高于width,也就是此时flex-basis代替项目的width属性。

当容器设置flex-direction为column或column-reverse时,flex-basis和height同时存在,flex-basis优先级高于height,也就是此时flex-basis代替项目的height属性。

需要注意的是,当flex-basis和width(或height),其中一个属性值为auto时,非auto的优先级更高。

.item{

flex-basis: auto(默认值) | <number>px

}

运行效果如图2-xx所示。

图4-15 flex-basis

创建名称为flexBasis的小程序项目。

WXML示例代码如下:

<view>row</view>

<view>当容器设置flex-direction为row时,flex-basis和width同时存在,</view>

<view>flex-basis优先级高于width,也就是此时flex-basis代替项目的width属性。</view>

<view class="container_row">

  <view style="background-color: red; width: 100px; flex-basis: 200px;">AAAAAA1</view>

  <view style="background-color: green;width: 200px;">BBBBBB2</view>

</view>

<view style="background-color: blue; width: 100px;">CCCCCC3</view>

<view>row-reverse</view>

<view>当容器设置flex-direction为row-reverse时,flex-basis和width同时存在,</view>

<view>flex-basis优先级高于width,也就是此时flex-basis代替项目的width属性。</view>

<view class="container_row_reverse">

  <view style="background-color: red; width: 100px; flex-basis: 200px;">AAAAAA1</view>

  <view style="background-color: green;width: 200px;">BBBBBB2</view>

</view>

<view style="background-color: blue; width: 100px;">CCCCCC3</view>

<view>column</view>

<view>当容器设置flex-direction为column时,flex-basis和height同时存在,</view>

<view>flex-basis优先级高于height,也就是此时flex-basis代替项目的height属性。</view>

<view class="container_column">

  <view style="background-color: red; height: 30px; flex-basis: 90px;">AAAAAA1</view>

  <view style="background-color: green;height: 90px;">BBBBBB2</view>

  <view style="background-color: blue;height: 30px;">CCCCCC3</view>

</view>

<view>column-reverse</view>

<view>当容器设置flex-direction为column-reverse时,flex-basis和height同时存在,</view>

<view>flex-basis优先级高于height,也就是此时flex-basis代替项目的height属性。</view>

<view class="container_column_reverse">

  <view style="background-color: red; height: 30px; flex-basis: 90px;">AAAAAA1</view>

  <view style="background-color: green;height: 90px;">BBBBBB2</view>

  <view style="background-color: blue;height: 30px;">CCCCCC3</view>

</view>

<view>row</view>

<view>flex-basis: 200px;</view>

<view>width: auto;</view>

<view>flex-basis优先级高</view>

<view class="container_row">

  <view style="background-color: red; width: auto; flex-basis: 200px;">AAAAAA1</view>

  <view style="background-color: green;width: 200px;">BBBBBB2</view>

</view>

<view style="background-color: blue; width: 100px;">CCCCCC3</view>

<view>column</view>

<view>flex-basis: auto;</view>

<view>height: 30px;</view>

<view>height优先级高</view>

<view class="container_column">

  <view style="background-color: red; height: 30px; flex-basis: auto;">AAAAAA1</view>

  <view style="background-color: green;height: 90px;">BBBBBB2</view>

  <view style="background-color: blue;height: 30px;">CCCCCC3</view>

</view>

WXSS示例代码如下:

.container_row {

  display: flex;

  flex-direction: row;

  flex-wrap: wrap;

  background-color: #cccccc;

}

.container_row_reverse {

  display: flex;

  flex-direction: row-reverse;

  flex-wrap: wrap;

  background-color: #cccccc;

}

.container_column {

  display: flex;

  flex-direction: column;

  background-color: #cccccc;

}

.container_column_reverse {

  display: flex;

  flex-direction: column-reverse;

  background-color: #cccccc;

}

程序运行效果如图2-xx所示。

图2-xx 运行效果

程序运行效果如图2-xx所示。

图2-xx 运行效果

程序运行效果如图2-xx所示。

图2-xx 运行效果

2.4.2.3.5 flex属性:flex-grow-flex-shrink-flex-basis简写方式

是flex-grow,flex-shrink,flex-basis的简写方式。值设置为none,等价于0 0 auto。值设置为auto,等价于1 1 auto。

.item{

flex: none | auto | @flex-grow @flex-shrink @flex-basis

}

2.4.2.3.6 align-self属性:覆盖容器的align-items

设置项目在行中交叉轴方向上的对齐方式,用于覆盖容器的align-items,这么做可以对项目的对齐方式做特殊处理。默认属性值为auto,继承容器的align-items值,当容器没有设置align-items时,属性值为stretch。

.item{

align-self: auto(默认值) | flex-start | center | flex-end | baseline |stretch

}

运行效果如图2-xx所示。

​图4-16 align-self

创建名称为alignSelf的小程序项目。

WXML示例代码如下:

<view>stretch</view>

<view class="container_stretch">

  <view style="background-color: red;">AAAAAA1</view>

  <view style="background-color: green;">BBBBBB2</view>

  <view style="background-color: blue;">CCCCCC3</view>

</view>

<view>flex-start</view>

<view class="container_stretch">

  <view style="background-color: pink; height: 50px; align-self: flex-start;">AAAAAA1</view>

  <view style="background-color: gold; height: 60px; align-self: flex-start;">BBBBBB2</view>

  <view style="background-color: aqua; height: 70px; align-self: flex-start;">CCCCCC3</view>

</view>

<view>flex-start</view>

<view class="container_flex_start">

  <view style="background-color: red; height: 50px;">AAAAAA1</view>

  <view style="background-color: green;height: 60px;">BBBBBB2</view>

  <view style="background-color: blue;height: 70px;">CCCCCC3</view>

</view>

<view>center</view>

<view class="container_flex_start">

  <view style="background-color: pink; height: 50px;align-self:center">AAAAAA1</view>

  <view style="background-color: gold;height: 60px;align-self:center">BBBBBB2</view>

  <view style="background-color: aqua;height: 70px;align-self:center">CCCCCC3</view>

</view>

<view>center</view>

<view class="container_center">

  <view style="background-color: red; height: 50px;">AAAAAA1</view>

  <view style="background-color: green;height: 60px;">BBBBBB2</view>

  <view style="background-color: blue;height: 70px;">CCCCCC3</view>

</view>

<view>flex-end</view>

<view class="container_center">

  <view style="background-color: pink; height: 50px;align-self:flex-end;">AAAAAA1</view>

  <view style="background-color: gold;height: 60px;align-self:flex-end;">BBBBBB2</view>

  <view style="background-color: aqua;height: 70px;align-self:flex-end;">CCCCCC3</view>

</view>

<view>flex-end</view>

<view class="container_flex_end">

  <view style="background-color: red; height: 50px;">AAAAAA1</view>

  <view style="background-color: green;height: 60px;">BBBBBB2</view>

  <view style="background-color: blue;height: 70px;">CCCCCC3</view>

</view>

<view>baseline</view>

<view class="container_flex_end">

  <view style="background-color: pink; height: 50px;padding-top: 30px;align-self:baseline;">AAAAAA1</view>

  <view style="background-color: gold;height: 60px;align-self:baseline;">BBBBBB2</view>

  <view style="background-color: aqua;height: 70px;padding-top: 30px;align-self:baseline;">CCCCCC3</view>

</view>

<view>baseline</view>

<view class="container_baseline">

  <view style="background-color: red; height: 50px; padding-top: 30px;">AAAAAA1</view>

  <view style="background-color: green;height: 60px;">BBBBBB2</view>

  <view style="background-color: blue;height: 70px;padding-top: 30px;">CCCCCC3</view>

</view>

<view>stretch</view>

<view class="container_baseline">

  <view style="background-color: pink; height: 50px; padding-top: 30px; align-self: stretch;">AAAAAA1</view>

  <view style="background-color: gold;height: 60px; align-self: stretch;">BBBBBB2</view>

  <view style="background-color: aqua;height: 70px;padding-top: 30px; align-self: stretch;">CCCCCC3</view>

</view>

WXSS示例代码如下:

.container_stretch {

  display: flex;

  align-items: stretch;

  height: 100px;

  background-color: #cccccc;

}

.container_flex_start {

  display: flex;

  align-items: flex-start;

  background-color: #cccccc;

}

.container_center {

  display: flex;

  align-items: center;

  background-color: #cccccc;

}

.container_flex_end {

  display: flex;

  align-items: flex-end;

  background-color: #cccccc;

}

.container_baseline {

  display: flex;

  align-items: baseline;

  background-color: #cccccc;

}

程序运行效果如图2-xx所示。

图2-xx 运行效果

程序运行效果如图2-xx所示。

图2-xx 运行效果

2.4.3 界面常见的交互反馈

用户和小程序在进行交互的时候,某些操作可能比较耗时,应该予以及时的反馈以舒缓用户等待的不良情绪。

2.4.3.1 触摸反馈

当页面摆放一些button按钮或者view区域,用户触摸按钮之后会触发下一步的操作。这种情况下要对触摸这个行为给予用户一些响应。如图2-xx所示,当手指触摸了button文字所在的cell区域时,对应的区域底色变成浅灰色,这样用户就可以知道小程序是有及时响应这次触摸操作的,用户就不会很迷惑。

图4-17 响应用户的触摸操作

小程序的view容器组件和button组件提供了hover-class属性,触摸时会在该组件加上对应的class,以改变组件的样式。

创建名称为hoverClass的小程序项目。

WXML示例代码如下:

<button hover-class="hover"> 点击button </button>

<view hover-class="hover"> 点击view</view>

WXSS示例代码如下:

.hover {

  background-color: gray;

}

程序运行效果如图2-xx所示。

图2-xx 运行效果

程序运行效果如图2-xx所示。

图2-xx 运行效果

程序运行效果如图2-xx所示。

图2-xx 运行效果

对于用户的操作进行及时的响应是非常优秀的使用体验,有时候在点击button按钮处理更耗时的操作时也会使用button组件的loading属性,在按钮的文字前边出现一个Loading,让用户明确的感觉到这个操作会比较耗时,需要等待一小段时间。效果如图2-xx所示。

图2-xx button文字前面出现loading状态

创建名称为buttonLoading的小程序项目。

WXML示例代码如下:

<button loading="{{loading}}" bindtap="tap">操作</button>

JS示例代码如下:

Page({

  data: { loading: false },

  tap: function () {

    //把按钮的loading状态显示出来

    this.setData({

      loading: true

    })

    //接着做耗时的操作

  }

})

程序运行效果如图2-xx所示。

图2-xx 运行效果

2.4.3.2 Toast和模态对话框

在完成某个操作成功之后,希望告诉用户这次操作是成功的并且不打断用户接下来的操作,那么弹出式提示Toast就是用在这样的场景上。Toast提示默认1.5秒之后自动消失,其表现形式如图2-xx所示。

图2-xx Toast弹出式提示

小程序提供了显示和隐藏Toast的接口。

创建名称为Toast的小程序项目。

WXML示例代码如下:

<view><button bind:tap="showMethod">显示</button></view>

<view><button bind:tap="hideMethod">隐藏</button></view>

JS示例代码如下:

Page({

  showMethod() {

    //显示Toast

    wx.showToast({

      title: '已发送',

      icon: 'success',

      duration: 5000

    })

  },

  hideMethod() {

    //隐藏Toast

    wx.hideToast();

  }

})

程序运行效果如图2-xx所示。

图2-xx 运行效果

特别要注意,不应该把Toast用于错误提示,因为错误提示需要明确告知用户具体的原因,因此不适合用这种一闪而过的Toast弹出式提示。一般需要用户明确知晓操作结果状态的话,会使用模态对话框来提示,同时附带下一步操作的指引,效果如图2-xx所示。

图2-xx 模态对话框

创建名称为showModal的小程序项目。

WXML示例代码如下:

<view><button bind:tap="showMethod">显示</button></view>

JS示例代码如下:

Page({

  showMethod() {

    wx.showModal({

      title: '标题',

      content: '告知当前状态,信息和解决方法',

      confirmText: '主操作',

      cancelText: '次要操作',

      success: function (res) {

        if (res.confirm) {

          console.log('用户点击主操作')

        } else if (res.cancel) {

          console.log('用户点击次要操作')

        }

      }

    })

  }

})

程序运行效果如图2-xx所示。

图2-xx 运行效果

2.4.3.3 界面滚动

往往手机屏幕是承载不了所有信息的,所以内容区域肯定会超出屏幕区域,用户可以通过滑动屏幕来查看下一屏的内容,这是非常常见的界面滚动的交互。

为了让用户可以快速刷新当前界面的信息,一般在小程序里会通过下拉整个界面这个操作来触发,效果如图2-xx所示。

图2-xx 运行效果

宿主环境提供了统一的下拉刷新交互,开发者只需要通过配置开启当前页面的下拉刷新,用户往下拉动界面触发下拉刷新操作时,Page构造器的onPullDownRefresh回调会被触发,此时开发者重新拉取新数据进行渲染。

示例代码如下:

//page.json

{ "enablePullDownRefresh": true }

//page.js

Page({

  onPullDownRefresh: function () {

    // 用户触发了下拉刷新操作

    // 拉取新数据重新渲染界面

// wx.stopPullDownRefresh()方法可以停止当前页面的下拉刷新

  }

})

事件onPullDownRefresh在前面章节介绍过,在此不再重复介绍。

多数的购物小程序会在首页展示一个商品列表,用户滚动到底部的时候,会加载下一页的商品列表渲染到列表的下方,把这样的交互操作称为“上拉触底”。宿主环境提供了上拉的配置和操作触发的回调,示例代码如下:

//page.json

// 界面的下方距离页面底部距离小于onReachBottomDistance像素时触发onReachBottom回调

{ "onReachBottomDistance": 100 }

//page.js

Page({

  onReachBottom: function () {

    // 当界面的下方距离页面底部距离小于100像素时触发回调

  }

})

事件onReachBottom在前面章节介绍过,在此不再重复介绍。

当然有些时候并不想整个页面进行滚动刷新,而是页面中某一小块区域需要可滚动,此时就要使用到宿主环境提供的scroll-view可滚动视图组件。可以通过组件的scroll-x和scroll-y属性决定滚动区域是否可以横向或者纵向滚动,scroll-view组件也提供了丰富的滚动回调触发事件,有关scroll-view组件不再展开细节,可以通过scroll-view组件的官方文档了解到更多的使用细节。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 2.4 场景应用
    • 2.4.1 开发流程基本介绍
    • 2.4.2 基本的布局方法:Flex布局
    • 2.4.3 界面常见的交互反馈
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档